Fixes null key handling in incoming query strings.
[dotnetoauth.git] / src / DotNetOpenAuth.Test / CoordinatorBase.cs
blobfdb29918ab2d9c3cf0b71ea138072b9a662491b2
1 //-----------------------------------------------------------------------
2 // <copyright file="CoordinatorBase.cs" company="Andrew Arnott">
3 // Copyright (c) Andrew Arnott. All rights reserved.
4 // </copyright>
5 //-----------------------------------------------------------------------
7 namespace DotNetOpenAuth.Test {
8 using System;
9 using System.Threading;
10 using DotNetOpenAuth.Messaging;
11 using DotNetOpenAuth.OpenId.RelyingParty;
12 using DotNetOpenAuth.Test.Mocks;
13 using Microsoft.VisualStudio.TestTools.UnitTesting;
15 internal abstract class CoordinatorBase<T1, T2> {
16 private Action<T1> party1Action;
17 private Action<T2> party2Action;
19 protected CoordinatorBase(Action<T1> party1Action, Action<T2> party2Action) {
20 ErrorUtilities.VerifyArgumentNotNull(party1Action, "party1Action");
21 ErrorUtilities.VerifyArgumentNotNull(party2Action, "party2Action");
23 this.party1Action = party1Action;
24 this.party2Action = party2Action;
27 protected internal Action<IProtocolMessage> IncomingMessageFilter { get; set; }
29 protected internal Action<IProtocolMessage> OutgoingMessageFilter { get; set; }
31 internal abstract void Run();
33 protected void RunCore(T1 party1Object, T2 party2Object) {
34 Thread party1Thread = null, party2Thread = null;
35 Exception failingException = null;
37 // Each thread we create needs a surrounding exception catcher so that we can
38 // terminate the other thread and inform the test host that the test failed.
39 Action<Action> safeWrapper = (action) => {
40 try {
41 action();
42 } catch (Exception ex) {
43 // We may be the second thread in an ThreadAbortException, so check the "flag"
44 lock (this) {
45 if (failingException == null || (failingException is ThreadAbortException && !(ex is ThreadAbortException))) {
46 failingException = ex;
47 if (Thread.CurrentThread == party1Thread) {
48 party2Thread.Abort();
49 } else {
50 party1Thread.Abort();
57 // Run the threads, and wait for them to complete.
58 // If this main thread is aborted (test run aborted), go ahead and abort the other two threads.
59 party1Thread = new Thread(() => { safeWrapper(() => { this.party1Action(party1Object); }); });
60 party2Thread = new Thread(() => { safeWrapper(() => { this.party2Action(party2Object); }); });
61 try {
62 party1Thread.Start();
63 party2Thread.Start();
64 party1Thread.Join();
65 party2Thread.Join();
66 } catch (ThreadAbortException) {
67 party1Thread.Abort();
68 party2Thread.Abort();
69 throw;
72 // Use the failing reason of a failing sub-thread as our reason, if anything failed.
73 if (failingException != null) {
74 throw new AssertFailedException("Coordinator thread threw unhandled exception: " + failingException, failingException);