summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/DotNetOpenAuth.Test/CoordinatorBase.cs68
-rw-r--r--src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj11
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/ErrorUtilitiesTests.cs39
-rw-r--r--src/DotNetOpenAuth.Test/Mocks/CoordinatingOAuthChannel.cs (renamed from src/DotNetOpenAuth.Test/Scenarios/CoordinatingOAuthChannel.cs)2
-rw-r--r--src/DotNetOpenAuth.Test/OAuth/AppendixScenarios.cs (renamed from src/DotNetOpenAuth.Test/Scenarios/AppendixScenarios.cs)5
-rw-r--r--src/DotNetOpenAuth.Test/OAuth/OAuthCoordinator.cs67
-rw-r--r--src/DotNetOpenAuth.Test/Scenarios/Coordinator.cs120
-rw-r--r--src/DotNetOpenAuth.sln2
-rw-r--r--src/DotNetOpenAuth/Messaging/ErrorUtilities.cs26
-rw-r--r--src/DotNetOpenAuth/Messaging/MessagingStrings.Designer.cs9
-rw-r--r--src/DotNetOpenAuth/Messaging/MessagingStrings.resx3
11 files changed, 224 insertions, 128 deletions
diff --git a/src/DotNetOpenAuth.Test/CoordinatorBase.cs b/src/DotNetOpenAuth.Test/CoordinatorBase.cs
new file mode 100644
index 0000000..27d5930
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/CoordinatorBase.cs
@@ -0,0 +1,68 @@
+//-----------------------------------------------------------------------
+// <copyright file="CoordinatorBase.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test {
+ using System;
+ using System.Threading;
+ using DotNetOpenAuth.Messaging;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+ internal abstract class CoordinatorBase<T1, T2> {
+ private Action<T1> party1Action;
+ private Action<T2> party2Action;
+
+ protected CoordinatorBase(Action<T1> party1Action, Action<T2> party2Action) {
+ ErrorUtilities.VerifyArgumentNotNull(party1Action, "party1Action");
+ ErrorUtilities.VerifyArgumentNotNull(party2Action, "party2Action");
+
+ this.party1Action = party1Action;
+ this.party2Action = party2Action;
+ }
+
+ protected void RunCore(T1 party1Object, T2 party2Object) {
+ Thread party1Thread = null, party2Thread = null;
+ Exception failingException = null;
+
+ // Each thread we create needs a surrounding exception catcher so that we can
+ // terminate the other thread and inform the test host that the test failed.
+ Action<Action> safeWrapper = (action) => {
+ try {
+ action();
+ } catch (Exception ex) {
+ // We may be the second thread in an ThreadAbortException, so check the "flag"
+ if (failingException == null) {
+ failingException = ex;
+ if (Thread.CurrentThread == party1Thread) {
+ party2Thread.Abort();
+ } else {
+ party1Thread.Abort();
+ }
+ }
+ }
+ };
+
+ // Run the threads, and wait for them to complete.
+ // If this main thread is aborted (test run aborted), go ahead and abort the other two threads.
+ party1Thread = new Thread(() => { safeWrapper(() => { this.party1Action(party1Object); }); });
+ party2Thread = new Thread(() => { safeWrapper(() => { this.party2Action(party2Object); }); });
+ try {
+ party1Thread.Start();
+ party2Thread.Start();
+ party1Thread.Join();
+ party2Thread.Join();
+ } catch (ThreadAbortException) {
+ party1Thread.Abort();
+ party2Thread.Abort();
+ throw;
+ }
+
+ // Use the failing reason of a failing sub-thread as our reason, if anything failed.
+ if (failingException != null) {
+ throw new AssertFailedException("Coordinator thread threw unhandled exception: " + failingException, failingException);
+ }
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
index b580064..d4b3b56 100644
--- a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
+++ b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
@@ -58,7 +58,9 @@
</Reference>
</ItemGroup>
<ItemGroup>
+ <Compile Include="CoordinatorBase.cs" />
<Compile Include="Messaging\CollectionAssert.cs" />
+ <Compile Include="Messaging\ErrorUtilitiesTests.cs" />
<Compile Include="Messaging\MessageSerializerTests.cs" />
<Compile Include="Messaging\Reflection\MessageDescriptionTests.cs" />
<Compile Include="Messaging\Reflection\MessageDictionaryTests.cs" />
@@ -102,9 +104,9 @@
<Compile Include="OpenId\Messages\IndirectErrorResponseTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Messaging\ResponseTests.cs" />
- <Compile Include="Scenarios\AppendixScenarios.cs" />
- <Compile Include="Scenarios\CoordinatingOAuthChannel.cs" />
- <Compile Include="Scenarios\Coordinator.cs" />
+ <Compile Include="OAuth\AppendixScenarios.cs" />
+ <Compile Include="Mocks\CoordinatingOAuthChannel.cs" />
+ <Compile Include="OAuth\OAuthCoordinator.cs" />
<Compile Include="TestBase.cs" />
<Compile Include="TestUtilities.cs" />
<Compile Include="UriUtilTests.cs" />
@@ -121,6 +123,9 @@
<ItemGroup>
<Shadow Include="Test References\DotNetOpenAuth.accessor" />
</ItemGroup>
+ <ItemGroup>
+ <Folder Include="Scenarios\" />
+ </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\tools\DotNetOpenAuth.Versioning.targets" />
</Project> \ No newline at end of file
diff --git a/src/DotNetOpenAuth.Test/Messaging/ErrorUtilitiesTests.cs b/src/DotNetOpenAuth.Test/Messaging/ErrorUtilitiesTests.cs
new file mode 100644
index 0000000..36b6ae7
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/Messaging/ErrorUtilitiesTests.cs
@@ -0,0 +1,39 @@
+//-----------------------------------------------------------------------
+// <copyright file="ErrorUtilitiesTests.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test.Messaging {
+ using System;
+ using DotNetOpenAuth.Messaging;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+ [TestClass]
+ public class ErrorUtilitiesTests {
+ [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ public void VerifyArgumentNotNullThrows() {
+ ErrorUtilities.VerifyArgumentNotNull(null, "someArg");
+ }
+
+ [TestMethod]
+ public void VerifyArgumentNotNullDoesNotThrow() {
+ ErrorUtilities.VerifyArgumentNotNull("hi", "someArg");
+ }
+
+ [TestMethod, ExpectedException(typeof(ArgumentNullException))]
+ public void VerifyNonZeroLengthOnNull() {
+ ErrorUtilities.VerifyNonZeroLength(null, "someArg");
+ }
+
+ [TestMethod, ExpectedException(typeof(ArgumentException))]
+ public void VerifyNonZeroLengthOnEmpty() {
+ ErrorUtilities.VerifyNonZeroLength(string.Empty, "someArg");
+ }
+
+ [TestMethod]
+ public void VerifyNonZeroLengthOnNonEmpty() {
+ ErrorUtilities.VerifyNonZeroLength("some Value", "someArg");
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/Scenarios/CoordinatingOAuthChannel.cs b/src/DotNetOpenAuth.Test/Mocks/CoordinatingOAuthChannel.cs
index 0fa474e..ce45572 100644
--- a/src/DotNetOpenAuth.Test/Scenarios/CoordinatingOAuthChannel.cs
+++ b/src/DotNetOpenAuth.Test/Mocks/CoordinatingOAuthChannel.cs
@@ -4,7 +4,7 @@
// </copyright>
//-----------------------------------------------------------------------
-namespace DotNetOpenAuth.Test.Scenarios {
+namespace DotNetOpenAuth.Test.Mocks {
using System;
using System.Threading;
using DotNetOpenAuth.Messaging;
diff --git a/src/DotNetOpenAuth.Test/Scenarios/AppendixScenarios.cs b/src/DotNetOpenAuth.Test/OAuth/AppendixScenarios.cs
index 5fb7538..5d25cf9 100644
--- a/src/DotNetOpenAuth.Test/Scenarios/AppendixScenarios.cs
+++ b/src/DotNetOpenAuth.Test/OAuth/AppendixScenarios.cs
@@ -4,7 +4,7 @@
// </copyright>
//-----------------------------------------------------------------------
-namespace DotNetOpenAuth.Test {
+namespace DotNetOpenAuth.Test.OAuth {
using System;
using System.IO;
using System.Net;
@@ -12,7 +12,6 @@ namespace DotNetOpenAuth.Test {
using DotNetOpenAuth.OAuth;
using DotNetOpenAuth.OAuth.ChannelElements;
using DotNetOpenAuth.Test.Mocks;
- using DotNetOpenAuth.Test.Scenarios;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
@@ -31,7 +30,7 @@ namespace DotNetOpenAuth.Test {
MessageReceivingEndpoint accessPhotoEndpoint = new MessageReceivingEndpoint("http://photos.example.net/photos?file=vacation.jpg&size=original", HttpDeliveryMethods.AuthorizationHeaderRequest | HttpDeliveryMethods.GetRequest);
ConsumerDescription consumerDescription = new ConsumerDescription("dpf43f3p2l4k3l03", "kd94hf93k423kf44");
- Coordinator coordinator = new Coordinator(
+ OAuthCoordinator coordinator = new OAuthCoordinator(
consumerDescription,
serviceDescription,
consumer => {
diff --git a/src/DotNetOpenAuth.Test/OAuth/OAuthCoordinator.cs b/src/DotNetOpenAuth.Test/OAuth/OAuthCoordinator.cs
new file mode 100644
index 0000000..37d7e5b
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/OAuth/OAuthCoordinator.cs
@@ -0,0 +1,67 @@
+//-----------------------------------------------------------------------
+// <copyright file="OAuthCoordinator.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test {
+ using System;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OAuth;
+ using DotNetOpenAuth.Test.Mocks;
+
+ /// <summary>
+ /// Runs a Consumer and Service Provider simultaneously so they can interact in a full simulation.
+ /// </summary>
+ internal class OAuthCoordinator : CoordinatorBase<WebConsumer, ServiceProvider> {
+ private ConsumerDescription consumerDescription;
+ private ServiceProviderDescription serviceDescription;
+
+ /// <summary>Initializes a new instance of the <see cref="OAuthCoordinator"/> class.</summary>
+ /// <param name="consumerDescription">The description of the consumer.</param>
+ /// <param name="serviceDescription">The service description that will be used to construct the Consumer and ServiceProvider objects.</param>
+ /// <param name="consumerAction">The code path of the Consumer.</param>
+ /// <param name="serviceProviderAction">The code path of the Service Provider.</param>
+ internal OAuthCoordinator(ConsumerDescription consumerDescription, ServiceProviderDescription serviceDescription, Action<WebConsumer> consumerAction, Action<ServiceProvider> serviceProviderAction)
+ : base(consumerAction, serviceProviderAction) {
+ ErrorUtilities.VerifyArgumentNotNull(consumerDescription, "consumerDescription");
+ ErrorUtilities.VerifyArgumentNotNull(serviceDescription, "serviceDescription");
+
+ this.consumerDescription = consumerDescription;
+ this.serviceDescription = serviceDescription;
+ }
+
+ /// <summary>
+ /// Starts the simulation.
+ /// </summary>
+ internal void Run() {
+ // Clone the template signing binding element.
+ var signingElement = this.serviceDescription.CreateTamperProtectionElement();
+ var consumerSigningElement = signingElement.Clone();
+ var spSigningElement = signingElement.Clone();
+
+ // Prepare token managers
+ InMemoryTokenManager consumerTokenManager = new InMemoryTokenManager();
+ InMemoryTokenManager serviceTokenManager = new InMemoryTokenManager();
+ consumerTokenManager.AddConsumer(this.consumerDescription);
+ serviceTokenManager.AddConsumer(this.consumerDescription);
+
+ // Prepare channels that will pass messages directly back and forth.
+ CoordinatingOAuthChannel consumerChannel = new CoordinatingOAuthChannel(consumerSigningElement, true, consumerTokenManager);
+ CoordinatingOAuthChannel serviceProviderChannel = new CoordinatingOAuthChannel(spSigningElement, false, serviceTokenManager);
+ consumerChannel.RemoteChannel = serviceProviderChannel;
+ serviceProviderChannel.RemoteChannel = consumerChannel;
+
+ // Prepare the Consumer and Service Provider objects
+ WebConsumer consumer = new WebConsumer(this.serviceDescription, consumerTokenManager) {
+ OAuthChannel = consumerChannel,
+ ConsumerKey = this.consumerDescription.ConsumerKey,
+ };
+ ServiceProvider serviceProvider = new ServiceProvider(this.serviceDescription, serviceTokenManager) {
+ OAuthChannel = serviceProviderChannel,
+ };
+
+ this.RunCore(consumer, serviceProvider);
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/Scenarios/Coordinator.cs b/src/DotNetOpenAuth.Test/Scenarios/Coordinator.cs
deleted file mode 100644
index 0479092..0000000
--- a/src/DotNetOpenAuth.Test/Scenarios/Coordinator.cs
+++ /dev/null
@@ -1,120 +0,0 @@
-//-----------------------------------------------------------------------
-// <copyright file="Coordinator.cs" company="Andrew Arnott">
-// Copyright (c) Andrew Arnott. All rights reserved.
-// </copyright>
-//-----------------------------------------------------------------------
-
-namespace DotNetOpenAuth.Test.Scenarios {
- using System;
- using System.Threading;
- using DotNetOpenAuth.OAuth;
- using DotNetOpenAuth.Test.Mocks;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
-
- /// <summary>
- /// Runs a Consumer and Service Provider simultaneously so they can interact in a full simulation.
- /// </summary>
- internal class Coordinator {
- private ConsumerDescription consumerDescription;
- private ServiceProviderDescription serviceDescription;
- private Action<WebConsumer> consumerAction;
- private Action<ServiceProvider> serviceProviderAction;
-
- /// <summary>Initializes a new instance of the <see cref="Coordinator"/> class.</summary>
- /// <param name="consumerDescription">The description of the consumer.</param>
- /// <param name="serviceDescription">The service description that will be used to construct the Consumer and ServiceProvider objects.</param>
- /// <param name="consumerAction">The code path of the Consumer.</param>
- /// <param name="serviceProviderAction">The code path of the Service Provider.</param>
- internal Coordinator(ConsumerDescription consumerDescription, ServiceProviderDescription serviceDescription, Action<WebConsumer> consumerAction, Action<ServiceProvider> serviceProviderAction) {
- if (consumerDescription == null) {
- throw new ArgumentNullException("consumerDescription");
- }
- if (serviceDescription == null) {
- throw new ArgumentNullException("serviceDescription");
- }
- if (consumerAction == null) {
- throw new ArgumentNullException("consumerAction");
- }
- if (serviceProviderAction == null) {
- throw new ArgumentNullException("serviceProviderAction");
- }
-
- this.consumerDescription = consumerDescription;
- this.serviceDescription = serviceDescription;
- this.consumerAction = consumerAction;
- this.serviceProviderAction = serviceProviderAction;
- }
-
- /// <summary>
- /// Starts the simulation.
- /// </summary>
- internal void Run() {
- // Clone the template signing binding element.
- var signingElement = this.serviceDescription.CreateTamperProtectionElement();
- var consumerSigningElement = signingElement.Clone();
- var spSigningElement = signingElement.Clone();
-
- // Prepare token managers
- InMemoryTokenManager consumerTokenManager = new InMemoryTokenManager();
- InMemoryTokenManager serviceTokenManager = new InMemoryTokenManager();
- consumerTokenManager.AddConsumer(this.consumerDescription);
- serviceTokenManager.AddConsumer(this.consumerDescription);
-
- // Prepare channels that will pass messages directly back and forth.
- CoordinatingOAuthChannel consumerChannel = new CoordinatingOAuthChannel(consumerSigningElement, true, consumerTokenManager);
- CoordinatingOAuthChannel serviceProviderChannel = new CoordinatingOAuthChannel(spSigningElement, false, serviceTokenManager);
- consumerChannel.RemoteChannel = serviceProviderChannel;
- serviceProviderChannel.RemoteChannel = consumerChannel;
-
- // Prepare the Consumer and Service Provider objects
- WebConsumer consumer = new WebConsumer(this.serviceDescription, consumerTokenManager) {
- OAuthChannel = consumerChannel,
- ConsumerKey = this.consumerDescription.ConsumerKey,
- };
- ServiceProvider serviceProvider = new ServiceProvider(this.serviceDescription, serviceTokenManager) {
- OAuthChannel = serviceProviderChannel,
- };
-
- Thread consumerThread = null, serviceProviderThread = null;
- Exception failingException = null;
-
- // Each thread we create needs a surrounding exception catcher so that we can
- // terminate the other thread and inform the test host that the test failed.
- Action<Action> safeWrapper = (action) => {
- try {
- action();
- } catch (Exception ex) {
- // We may be the second thread in an ThreadAbortException, so check the "flag"
- if (failingException == null) {
- failingException = ex;
- if (Thread.CurrentThread == consumerThread) {
- serviceProviderThread.Abort();
- } else {
- consumerThread.Abort();
- }
- }
- }
- };
-
- // Run the threads, and wait for them to complete.
- // If this main thread is aborted (test run aborted), go ahead and abort the other two threads.
- consumerThread = new Thread(() => { safeWrapper(() => { consumerAction(consumer); }); });
- serviceProviderThread = new Thread(() => { safeWrapper(() => { serviceProviderAction(serviceProvider); }); });
- try {
- consumerThread.Start();
- serviceProviderThread.Start();
- consumerThread.Join();
- serviceProviderThread.Join();
- } catch (ThreadAbortException) {
- consumerThread.Abort();
- serviceProviderThread.Abort();
- throw;
- }
-
- // Use the failing reason of a failing sub-thread as our reason, if anything failed.
- if (failingException != null) {
- throw new AssertFailedException("Coordinator thread threw unhandled exception: " + failingException, failingException);
- }
- }
- }
-}
diff --git a/src/DotNetOpenAuth.sln b/src/DotNetOpenAuth.sln
index e636d1b..6707b28 100644
--- a/src/DotNetOpenAuth.sln
+++ b/src/DotNetOpenAuth.sln
@@ -63,7 +63,7 @@ Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "ServiceProvider", "..\sampl
Release.AspNetCompiler.ForceOverwrite = "true"
Release.AspNetCompiler.FixedNames = "false"
Release.AspNetCompiler.Debug = "False"
- VWDPort = "65169"
+ VWDPort = "37480"
DefaultWebSiteLanguage = "Visual C#"
EndProjectSection
EndProject
diff --git a/src/DotNetOpenAuth/Messaging/ErrorUtilities.cs b/src/DotNetOpenAuth/Messaging/ErrorUtilities.cs
index b16cb0e..8464066 100644
--- a/src/DotNetOpenAuth/Messaging/ErrorUtilities.cs
+++ b/src/DotNetOpenAuth/Messaging/ErrorUtilities.cs
@@ -50,5 +50,31 @@ namespace DotNetOpenAuth.Messaging {
args));
}
}
+
+ /// <summary>
+ /// Verifies that some given value is not null.
+ /// </summary>
+ /// <param name="value">The value to check.</param>
+ /// <param name="paramName">Name of the parameter, which will be used in the <see cref="ArgumentException"/>, if thrown.</param>
+ /// <exception cref="ArgumentNullException">Thrown if <paramref name="value"/> is null.</exception>
+ internal static void VerifyArgumentNotNull(object value, string paramName) {
+ if (Object.ReferenceEquals(value, null)) {
+ throw new ArgumentNullException(paramName);
+ }
+ }
+
+ /// <summary>
+ /// Verifies that some string is not null and has non-zero length.
+ /// </summary>
+ /// <param name="value">The value to check.</param>
+ /// <param name="paramName">Name of the parameter, which will be used in the <see cref="ArgumentException"/>, if thrown.</param>
+ /// <exception cref="ArgumentNullException">Thrown if <paramref name="value"/> is null.</exception>
+ /// <exception cref="ArgumentException">Thrown if <paramref name="value"/> has zero length.</exception>
+ internal static void VerifyNonZeroLength(string value, string paramName) {
+ VerifyArgumentNotNull(value, paramName);
+ if (value.Length == 0) {
+ throw new ArgumentException(MessagingStrings.UnexpectedEmptyString, paramName);
+ }
+ }
}
}
diff --git a/src/DotNetOpenAuth/Messaging/MessagingStrings.Designer.cs b/src/DotNetOpenAuth/Messaging/MessagingStrings.Designer.cs
index 5733fc9..cd3cba1 100644
--- a/src/DotNetOpenAuth/Messaging/MessagingStrings.Designer.cs
+++ b/src/DotNetOpenAuth/Messaging/MessagingStrings.Designer.cs
@@ -376,6 +376,15 @@ namespace DotNetOpenAuth.Messaging {
}
/// <summary>
+ /// Looks up a localized string similar to The empty string is not allowed..
+ /// </summary>
+ internal static string UnexpectedEmptyString {
+ get {
+ return ResourceManager.GetString("UnexpectedEmptyString", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to Message parameter &apos;{0}&apos; had unexpected value &apos;{1}&apos;..
/// </summary>
internal static string UnexpectedMessagePartValue {
diff --git a/src/DotNetOpenAuth/Messaging/MessagingStrings.resx b/src/DotNetOpenAuth/Messaging/MessagingStrings.resx
index 262d084..5f5b9b4 100644
--- a/src/DotNetOpenAuth/Messaging/MessagingStrings.resx
+++ b/src/DotNetOpenAuth/Messaging/MessagingStrings.resx
@@ -222,6 +222,9 @@
<data name="TooManyBindingsOfferingSameProtection" xml:space="preserve">
<value>Expected at most 1 binding element offering the {0} protection, but found {1}.</value>
</data>
+ <data name="UnexpectedEmptyString" xml:space="preserve">
+ <value>The empty string is not allowed.</value>
+ </data>
<data name="UnexpectedMessagePartValue" xml:space="preserve">
<value>Message parameter '{0}' had unexpected value '{1}'.</value>
</data>