191 lines
6.7 KiB
C#
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(); }
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|