Jo Shields a575963da9 Imported Upstream version 3.6.0
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
2014-08-13 10:39:27 +01:00

191 lines
6.7 KiB
C#

// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Threading;
using System.Web.Mvc.Async;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace Microsoft.Web.Mvc.Test
{
public class AsyncManagerExtensionsTest
{
[Fact]
public void RegisterTask_AsynchronousCompletion()
{
// Arrange
SimpleSynchronizationContext syncContext = new SimpleSynchronizationContext();
AsyncManager asyncManager = new AsyncManager(syncContext);
bool endDelegateWasCalled = false;
ManualResetEvent waitHandle = new ManualResetEvent(false /* initialState */);
Func<AsyncCallback, IAsyncResult> beginDelegate = callback =>
{
Assert.Equal(1, asyncManager.OutstandingOperations.Count);
MockAsyncResult asyncResult = new MockAsyncResult(false /* completedSynchronously */);
ThreadPool.QueueUserWorkItem(_ =>
{
Assert.Equal(1, asyncManager.OutstandingOperations.Count);
callback(asyncResult);
waitHandle.Set();
});
return asyncResult;
};
Action<IAsyncResult> endDelegate = delegate { endDelegateWasCalled = true; };
// Act
asyncManager.RegisterTask(beginDelegate, endDelegate);
waitHandle.WaitOne();
// Assert
Assert.True(endDelegateWasCalled);
Assert.True(syncContext.SendWasCalled);
Assert.Equal(0, asyncManager.OutstandingOperations.Count);
}
[Fact]
public void RegisterTask_AsynchronousCompletion_SwallowsExceptionsThrownByEndDelegate()
{
// Arrange
SimpleSynchronizationContext syncContext = new SimpleSynchronizationContext();
AsyncManager asyncManager = new AsyncManager(syncContext);
bool endDelegateWasCalled = false;
ManualResetEvent waitHandle = new ManualResetEvent(false /* initialState */);
Func<AsyncCallback, IAsyncResult> beginDelegate = callback =>
{
MockAsyncResult asyncResult = new MockAsyncResult(false /* completedSynchronously */);
ThreadPool.QueueUserWorkItem(_ =>
{
callback(asyncResult);
waitHandle.Set();
});
return asyncResult;
};
Action<IAsyncResult> endDelegate = delegate
{
endDelegateWasCalled = true;
throw new Exception("This is a sample exception.");
};
// Act
asyncManager.RegisterTask(beginDelegate, endDelegate);
waitHandle.WaitOne();
// Assert
Assert.True(endDelegateWasCalled);
Assert.Equal(0, asyncManager.OutstandingOperations.Count);
}
[Fact]
public void RegisterTask_ResetsOutstandingOperationCountIfBeginMethodThrows()
{
// Arrange
SimpleSynchronizationContext syncContext = new SimpleSynchronizationContext();
AsyncManager asyncManager = new AsyncManager(syncContext);
Func<AsyncCallback, IAsyncResult> beginDelegate = cb => { throw new InvalidOperationException("BeginDelegate throws."); };
Action<IAsyncResult> endDelegate = ar => { Assert.True(false, "This should never be called."); };
// Act & assert
Assert.Throws<InvalidOperationException>(
delegate { asyncManager.RegisterTask(beginDelegate, endDelegate); }, "BeginDelegate throws.");
Assert.Equal(0, asyncManager.OutstandingOperations.Count);
}
[Fact]
public void RegisterTask_SynchronousCompletion()
{
// Arrange
SimpleSynchronizationContext syncContext = new SimpleSynchronizationContext();
AsyncManager asyncManager = new AsyncManager(syncContext);
bool endDelegateWasCalled = false;
Func<AsyncCallback, IAsyncResult> beginDelegate = callback =>
{
Assert.Equal(1, asyncManager.OutstandingOperations.Count);
MockAsyncResult asyncResult = new MockAsyncResult(true /* completedSynchronously */);
callback(asyncResult);
return asyncResult;
};
Action<IAsyncResult> endDelegate = delegate { endDelegateWasCalled = true; };
// Act
asyncManager.RegisterTask(beginDelegate, endDelegate);
// Assert
Assert.True(endDelegateWasCalled);
Assert.False(syncContext.SendWasCalled);
Assert.Equal(0, asyncManager.OutstandingOperations.Count);
}
[Fact]
public void RegisterTask_ThrowsIfAsyncManagerIsNull()
{
// Act & assert
Assert.ThrowsArgumentNull(
delegate { AsyncManagerExtensions.RegisterTask(null, _ => null, _ => { }); }, "asyncManager");
}
[Fact]
public void RegisterTask_ThrowsIfBeginDelegateIsNull()
{
// Act & assert
Assert.ThrowsArgumentNull(
delegate { new AsyncManager().RegisterTask(null, _ => { }); }, "beginDelegate");
}
[Fact]
public void RegisterTask_ThrowsIfEndDelegateIsNull()
{
// Act & assert
Assert.ThrowsArgumentNull(
delegate { new AsyncManager().RegisterTask(_ => null, null); }, "endDelegate");
}
private class SimpleSynchronizationContext : SynchronizationContext
{
public bool SendWasCalled;
public override void Send(SendOrPostCallback d, object state)
{
SendWasCalled = true;
d(state);
}
}
private class MockAsyncResult : IAsyncResult
{
private readonly bool _completedSynchronously;
public MockAsyncResult(bool completedSynchronously)
{
_completedSynchronously = completedSynchronously;
}
public object AsyncState
{
get { throw new NotImplementedException(); }
}
public WaitHandle AsyncWaitHandle
{
get { throw new NotImplementedException(); }
}
public bool CompletedSynchronously
{
get { return _completedSynchronously; }
}
public bool IsCompleted
{
get { throw new NotImplementedException(); }
}
}
}
}