Merge fixes of TestExecutionContext and testContext for async tests

This commit is contained in:
Charlie Poole 2012-10-14 15:22:11 -07:00
Родитель ebb09da36a 36d0dd5619
Коммит 5105746728
9 изменённых файлов: 209 добавлений и 64 удалений

Просмотреть файл

@ -6,12 +6,15 @@
using System;
using System.Collections;
using System.Runtime.Remoting.Messaging;
namespace NUnit.Core
{
public class ContextDictionary : Hashtable
[Serializable]
public class ContextDictionary : MarshalByRefObject, IDictionary, ILogicalThreadAffinative
{
internal TestExecutionContext _context;
private readonly Hashtable _storage = new Hashtable();
public ContextDictionary() { }
@ -20,7 +23,7 @@ namespace NUnit.Core
_context = context;
}
public override object this[object key]
public object this[object key]
{
get
{
@ -43,13 +46,87 @@ namespace NUnit.Core
? _context.TestPackage.Settings["WorkDirectory"]
: Environment.CurrentDirectory;
default:
return base[key];
return _storage[key];
}
}
set
{
base[key] = value;
_storage[key] = value;
}
}
#region IDictionary Interface non-implementation
void IDictionary.Remove(object key)
{
throw new NotImplementedException();
}
ICollection IDictionary.Keys
{
get { throw new NotImplementedException(); }
}
ICollection IDictionary.Values
{
get { throw new NotImplementedException(); }
}
bool IDictionary.IsReadOnly
{
get { throw new NotImplementedException(); }
}
bool IDictionary.IsFixedSize
{
get { throw new NotImplementedException(); }
}
bool IDictionary.Contains(object key)
{
throw new NotImplementedException();
}
void IDictionary.Add(object key, object value)
{
throw new NotImplementedException();
}
void IDictionary.Clear()
{
throw new NotImplementedException();
}
IDictionaryEnumerator IDictionary.GetEnumerator()
{
throw new NotImplementedException();
}
IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
void ICollection.CopyTo(Array array, int index)
{
throw new NotImplementedException();
}
int ICollection.Count
{
get { throw new NotImplementedException(); }
}
object ICollection.SyncRoot
{
get { throw new NotImplementedException(); }
}
bool ICollection.IsSynchronized
{
get { throw new NotImplementedException(); }
}
#endregion
}
}
}

Просмотреть файл

@ -4,8 +4,6 @@
// obtain a copy of the license at http://nunit.org.
// ****************************************************************
using System;
using System.Collections.Specialized;
using System.Configuration;
using System.IO;
using System.Diagnostics;
using System.Globalization;
@ -398,7 +396,7 @@ namespace NUnit.Core
public static void Save()
{
current = new TestExecutionContext(current);
CallContext.SetData("NUnit.Framework.TestContext", current.contextDictionary);
CallContext.LogicalSetData("NUnit.Framework.TestContext", current.contextDictionary);
}
/// <summary>
@ -409,7 +407,7 @@ namespace NUnit.Core
{
current.ReverseChanges();
current = current.prior;
CallContext.SetData("NUnit.Framework.TestContext", current.contextDictionary);
CallContext.LogicalSetData("NUnit.Framework.TestContext", current.contextDictionary);
}
#endregion

Просмотреть файл

@ -91,7 +91,7 @@ namespace NUnit.Core
this.thrownException = null;
this.listener = listener;
this.filter = filter;
this.contextDictionary = (ContextDictionary)CallContext.GetData("NUnit.Framework.TestContext");
this.contextDictionary = (ContextDictionary)CallContext.LogicalGetData("NUnit.Framework.TestContext");
log.Debug("Starting test in separate thread");
thread.Start();
@ -133,7 +133,7 @@ namespace NUnit.Core
/// </summary>
private void RunTestProc()
{
CallContext.SetData("NUnit.Framework.TestContext", contextDictionary);
CallContext.LogicalSetData("NUnit.Framework.TestContext", contextDictionary);
try
{

Просмотреть файл

@ -1,7 +1,6 @@
#if NET_3_5 || NET_4_0 || NET_4_5
using System;
using System.Collections;
using System.Diagnostics;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading;
@ -27,37 +26,42 @@ namespace nunit.core.tests.net45
{
get
{
yield return new object[] { Method("VoidTestSuccess"), ResultState.Success, 1 };
yield return new object[] { Method("VoidTestFailure"), ResultState.Failure, 1 };
yield return new object[] { Method("VoidTestError"), ResultState.Error, 0 };
yield return new object[] { Method("VoidTestExpectedException"), ResultState.Success, 0 };
yield return new object[] { Method(f => f.VoidTestSuccess()), ResultState.Success, 1 };
yield return new object[] { Method(f => f.VoidTestFailure()), ResultState.Failure, 1 };
yield return new object[] { Method(f => f.VoidTestError()), ResultState.Error, 0 };
yield return new object[] { Method(f => f.VoidTestExpectedException()), ResultState.Success, 0 };
yield return new object[] { Method("TaskTestSuccess"), ResultState.Success, 1 };
yield return new object[] { Method("TaskTestFailure"), ResultState.Failure, 1 };
yield return new object[] { Method("TaskTestError"), ResultState.Error, 0 };
yield return new object[] { Method("TaskTestExpectedException"), ResultState.Success, 0 };
yield return new object[] { Method(f => f.TaskTestSuccess()), ResultState.Success, 1 };
yield return new object[] { Method(f => f.TaskTestFailure()), ResultState.Failure, 1 };
yield return new object[] { Method(f => f.TaskTestError()), ResultState.Error, 0 };
yield return new object[] { Method(f => f.TaskTestExpectedException()), ResultState.Success, 0 };
yield return new object[] { Method("TaskTTestCaseWithResultCheckSuccess"), ResultState.Success, 0 };
yield return new object[] { Method("TaskTTestCaseWithResultCheckFailure"), ResultState.Failure, 0 };
yield return new object[] { Method("TaskTTestCaseWithResultCheckError"), ResultState.Failure, 0 };
yield return new object[] { Method("TaskTTestCaseWithResultCheckSuccessReturningNull"), ResultState.Success, 0 };
yield return new object[] { Method("TaskTTestCaseWithoutResultCheckExpectedExceptionSuccess"), ResultState.Success, 0 };
yield return new object[] { Method(f => f.TaskTTestCaseWithResultCheckSuccess()), ResultState.Success, 0 };
yield return new object[] { Method(f => f.TaskTTestCaseWithResultCheckFailure()), ResultState.Failure, 0 };
yield return new object[] { Method(f => f.TaskTTestCaseWithResultCheckError()), ResultState.Failure, 0 };
yield return new object[] { Method(f => f.TaskTTestCaseWithResultCheckSuccessReturningNull()), ResultState.Success, 0 };
yield return new object[] { Method(f => f.TaskTTestCaseWithoutResultCheckExpectedExceptionSuccess()), ResultState.Success, 0 };
yield return new object[] { Method("NestedVoidTestSuccess"), ResultState.Success, 1 };
yield return new object[] { Method("NestedVoidTestFailure"), ResultState.Failure, 1 };
yield return new object[] { Method("NestedVoidTestError"), ResultState.Error, 0 };
yield return new object[] { Method(f => f.NestedVoidTestSuccess()), ResultState.Success, 1 };
yield return new object[] { Method(f => f.NestedVoidTestFailure()), ResultState.Failure, 1 };
yield return new object[] { Method(f => f.NestedVoidTestError()), ResultState.Error, 0 };
yield return new object[] { Method("NestedTaskTestSuccess"), ResultState.Success, 1 };
yield return new object[] { Method("NestedTaskTestFailure"), ResultState.Failure, 1 };
yield return new object[] { Method("NestedTaskTestError"), ResultState.Error, 0 };
yield return new object[] { Method(f => f.NestedTaskTestSuccess()), ResultState.Success, 1 };
yield return new object[] { Method(f => f.NestedTaskTestFailure()), ResultState.Failure, 1 };
yield return new object[] { Method(f => f.NestedTaskTestError()), ResultState.Error, 0 };
yield return new object[] { Method("VoidTestMultipleSuccess"), ResultState.Success, 1 };
yield return new object[] { Method("VoidTestMultipleFailure"), ResultState.Failure, 1 };
yield return new object[] { Method("VoidTestMultipleError"), ResultState.Error, 0 };
yield return new object[] { Method(f => f.VoidTestMultipleSuccess()), ResultState.Success, 1 };
yield return new object[] { Method(f => f.VoidTestMultipleFailure()), ResultState.Failure, 1 };
yield return new object[] { Method(f => f.VoidTestMultipleError()), ResultState.Error, 0 };
yield return new object[] { Method("TaskTestMultipleSuccess"), ResultState.Success, 1 };
yield return new object[] { Method("TaskTestMultipleFailure"), ResultState.Failure, 1 };
yield return new object[] { Method("TaskTestMultipleError"), ResultState.Error, 0 };
yield return new object[] { Method(f => f.TaskTestMultipleSuccess()), ResultState.Success, 1 };
yield return new object[] { Method(f => f.TaskTestMultipleFailure()), ResultState.Failure, 1 };
yield return new object[] { Method(f => f.TaskTestMultipleError()), ResultState.Error, 0 };
yield return new object[] { Method(f => f.VoidCheckTestContextAcrossTasks()), ResultState.Success, 2 };
yield return new object[] { Method(f => f.VoidCheckTestContextWithinTestBody()), ResultState.Success, 2 };
yield return new object[] { Method(f => f.TaskCheckTestContextAcrossTasks()), ResultState.Success, 2 };
yield return new object[] { Method(f => f.TaskCheckTestContextWithinTestBody()), ResultState.Success, 2 };
}
}
@ -81,7 +85,7 @@ namespace nunit.core.tests.net45
SynchronizationContext.SetSynchronizationContext(context);
var method = _builder.BuildFrom(Method("VoidAssertSynchrnoizationContext"));
var method = _builder.BuildFrom(Method(f => f.VoidAssertSynchronizationContext()));
var result = method.Run(new NullListener(), TestFilter.Empty);
@ -91,9 +95,9 @@ namespace nunit.core.tests.net45
Assert.That(result.AssertCount, Is.EqualTo(1), "Wrong assertion count");
}
private static MethodInfo Method(string name)
private static MethodInfo Method(Expression<Action<AsyncRealFixture>> action)
{
return typeof (AsyncRealFixture).GetMethod(name);
return ((MethodCallExpression)action.Body).Method;
}
public class CustomSynchronizationContext : SynchronizationContext

Просмотреть файл

@ -1,5 +1,7 @@
#if NET_3_5 || NET_4_0 || NET_4_5
using System;
using System.Collections;
using System.Linq.Expressions;
using System.Reflection;
using NUnit.Core;
using NUnit.Core.Builders;
@ -23,9 +25,9 @@ namespace nunit.core.tests.net45
{
get
{
yield return new object[] { Method("AsyncVoidTest"), RunState.Runnable };
yield return new object[] { Method("AsyncTaskTest"), RunState.Runnable };
yield return new object[] { Method("AsyncTaskTTest"), RunState.NotRunnable };
yield return new object[] { Method(f => f.AsyncVoidTest()), RunState.Runnable };
yield return new object[] { Method(f => f.AsyncTaskTest()), RunState.Runnable };
yield return new object[] { Method(f => f.AsyncTaskTTest()), RunState.NotRunnable };
}
}
@ -33,13 +35,13 @@ namespace nunit.core.tests.net45
{
get
{
yield return new object[] { Method("AsyncVoidTestCaseWithResultCheck"), RunState.NotRunnable };
yield return new object[] { Method("AsyncTaskTestCaseWithResultCheck"), RunState.NotRunnable };
yield return new object[] { Method("AsyncTaskTTestCaseWithResultCheck"), RunState.Runnable };
yield return new object[] { Method("AsyncVoidTestCaseWithoutResultCheck"), RunState.Runnable };
yield return new object[] { Method("AsyncTaskTestCaseWithoutResultCheck"), RunState.Runnable };
yield return new object[] { Method("AsyncTaskTTestCaseWithoutResultCheck"), RunState.NotRunnable };
yield return new object[] { Method("AsyncTaskTTestCaseExpectedExceptionWithoutResultCheck"), RunState.Runnable };
yield return new object[] { Method(f => f.AsyncVoidTestCaseWithResultCheck()), RunState.NotRunnable };
yield return new object[] { Method(f => f.AsyncTaskTestCaseWithResultCheck()), RunState.NotRunnable };
yield return new object[] { Method(f => f.AsyncTaskTTestCaseWithResultCheck()), RunState.Runnable };
yield return new object[] { Method(f => f.AsyncVoidTestCaseWithoutResultCheck()), RunState.Runnable };
yield return new object[] { Method(f => f.AsyncTaskTestCaseWithoutResultCheck()), RunState.Runnable };
yield return new object[] { Method(f => f.AsyncTaskTTestCaseWithoutResultCheck()), RunState.NotRunnable };
yield return new object[] { Method(f => f.AsyncTaskTTestCaseExpectedExceptionWithoutResultCheck()), RunState.Runnable };
}
}
@ -67,7 +69,7 @@ namespace nunit.core.tests.net45
[Test]
public void Non_async_task()
{
var built = _sut.BuildFrom(Method("NonAsyncTask"));
var built = _sut.BuildFrom(Method(f => f.NonAsyncTask()));
Assert.That(built, Is.Not.InstanceOf<NUnitAsyncTestMethod>());
Assert.That(built.RunState, Is.EqualTo(RunState.NotRunnable));
@ -76,15 +78,15 @@ namespace nunit.core.tests.net45
[Test]
public void Non_async_task_with_result()
{
var built = _sut.BuildFrom(Method("NonAsyncTaskWithResult"));
var built = _sut.BuildFrom(Method(f => f.NonAsyncTaskWithResult()));
Assert.That(built, Is.Not.InstanceOf<NUnitAsyncTestMethod>());
Assert.That(built.RunState, Is.EqualTo(RunState.NotRunnable));
}
public MethodInfo Method(string name)
private static MethodInfo Method(Expression<Action<AsyncDummyFixture>> action)
{
return typeof (AsyncDummyFixture).GetMethod(name);
return ((MethodCallExpression) action.Body).Method;
}
}
}

Просмотреть файл

@ -41,13 +41,13 @@ namespace NUnit.Core.Tests
[Test]
public void ILogicalThreadAffinativeTest()
{
CallContext.SetData( CONTEXT_DATA, new EmptyCallContextData() );
CallContext.LogicalSetData( CONTEXT_DATA, new EmptyCallContextData() );
}
[Test]
public void ILogicalThreadAffinativeTestConsole()
{
CallContext.SetData( CONTEXT_DATA, new EmptyCallContextData() );
CallContext.LogicalSetData( CONTEXT_DATA, new EmptyCallContextData() );
// TODO: make this Assertable
//Console.WriteLine("ILogicalThreadAffinativeTest");
Console.Out.Flush();
@ -60,7 +60,7 @@ namespace NUnit.Core.Tests
GenericPrincipal prpal = new GenericPrincipal(ident,
new string[] {"Level1"});
CallContext.SetData( CONTEXT_DATA, new PrincipalCallContextData( prpal ) );
CallContext.LogicalSetData( CONTEXT_DATA, new PrincipalCallContextData( prpal ) );
}
[Test]

Просмотреть файл

@ -6,6 +6,7 @@
using System;
using System.IO;
using System.Threading;
using NUnit.Framework;
using NUnit.TestData.TestContextData;
using NUnit.TestUtilities;
@ -232,9 +233,27 @@ namespace NUnit.Core.Tests
}
[Test, RequiresThread]
public void CanAccessTestContextOnSeparateThread()
public void CanAccessTestContextWhenRunningTestOnSeparateThread()
{
Assert.That(TestContext.CurrentContext.Test.Name, Is.EqualTo("CanAccessTestContextOnSeparateThread"));
Assert.That(TestContext.CurrentContext.Test.Name, Is.EqualTo("CanAccessTestContextWhenRunningTestOnSeparateThread"));
}
[Test]
public void CanAccessTestContextFromThreadSpawnWithinTest()
{
var testName = new object[1];
var thread = new Thread(FillTestNameFromContext);
thread.Start(testName);
thread.Join();
Assert.IsNotNull(testName[0]);
Assert.AreEqual(testName[0], TestContext.CurrentContext.Test.Name);
}
private static void FillTestNameFromContext(object arg)
{
((object[])arg)[0] = TestContext.CurrentContext.Test.Name;
}
}
}
}

Просмотреть файл

@ -47,7 +47,7 @@ namespace NUnit.Framework
{
get
{
return new TestContext((IDictionary)CallContext.GetData(contextKey));
return new TestContext((IDictionary)CallContext.LogicalGetData(contextKey));
}
}

Просмотреть файл

@ -101,7 +101,7 @@ namespace test_assembly_net45
}
[Test]
public async void VoidAssertSynchrnoizationContext()
public async void VoidAssertSynchronizationContext()
{
Assert.That(SynchronizationContext.Current, Is.InstanceOf<AsyncSynchronizationContext>());
await Task.Yield();
@ -174,7 +174,7 @@ namespace test_assembly_net45
[Test]
public async void VoidTestMultipleError()
{
var result = await ReturnOne();
await ReturnOne();
await ThrowException();
Assert.Fail("Should never get here");
@ -199,12 +199,57 @@ namespace test_assembly_net45
[Test]
public async Task TaskTestMultipleError()
{
var result = await ReturnOne();
await ReturnOne();
await ThrowException();
Assert.Fail("Should never get here");
}
[Test]
public async void VoidCheckTestContextAcrossTasks()
{
var testName = await GetTestNameFromContext();
Assert.IsNotNull(testName);
Assert.AreEqual(testName, TestContext.CurrentContext.Test.Name);
}
[Test]
public async Task TaskCheckTestContextAcrossTasks()
{
var testName = await GetTestNameFromContext();
Assert.IsNotNull(testName);
Assert.AreEqual(testName, TestContext.CurrentContext.Test.Name);
}
[Test]
public async void VoidCheckTestContextWithinTestBody()
{
var testName = TestContext.CurrentContext.Test.Name;
await ReturnOne();
Assert.IsNotNull(testName);
Assert.AreEqual(testName, TestContext.CurrentContext.Test.Name);
}
[Test]
public async Task TaskCheckTestContextWithinTestBody()
{
var testName = TestContext.CurrentContext.Test.Name;
await ReturnOne();
Assert.IsNotNull(testName);
Assert.AreEqual(testName, TestContext.CurrentContext.Test.Name);
}
private static Task<string> GetTestNameFromContext()
{
return Task.Run(() => TestContext.CurrentContext.Test.Name);
}
private static Task<int> ReturnOne()
{
return Task.Run(() => 1);