289 lines
8.7 KiB
C#
289 lines
8.7 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using AMWD.Common.Utilities;
|
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
|
|
namespace UnitTests.Common.Utilities
|
|
{
|
|
[TestClass]
|
|
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
|
|
public class DelayedTaskTests
|
|
{
|
|
[TestMethod]
|
|
public void ShouldCreateNewDelayedTaskNotStarting()
|
|
{
|
|
// arrange
|
|
int executionCount = 0;
|
|
var delay = TimeSpan.FromMilliseconds(100);
|
|
var action = () => { executionCount++; };
|
|
|
|
// act
|
|
var cts = new CancellationTokenSource(delay.Add(TimeSpan.FromSeconds(1)));
|
|
var delayedTask = DelayedTask.Create(action, delay);
|
|
SpinWait.SpinUntil(() => executionCount > 0 || cts.IsCancellationRequested);
|
|
|
|
// assert
|
|
Assert.IsNotNull(delayedTask);
|
|
Assert.AreEqual(delay, delayedTask.Delay);
|
|
Assert.IsFalse(delayedTask.IsRunning);
|
|
Assert.IsFalse(delayedTask.IsWaitingToRun);
|
|
Assert.IsNull(delayedTask.Exception);
|
|
Assert.AreEqual(0, executionCount);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void ShouldCreateNewDelayedTaskStarting()
|
|
{
|
|
// arrange
|
|
int executionCount = 0;
|
|
var delay = TimeSpan.FromMilliseconds(100);
|
|
var action = () => { executionCount++; };
|
|
|
|
// act
|
|
var cts = new CancellationTokenSource(delay.Add(TimeSpan.FromSeconds(1)));
|
|
var delayedTask = DelayedTask.Run(action, delay);
|
|
SpinWait.SpinUntil(() => executionCount > 0 || cts.IsCancellationRequested);
|
|
|
|
// assert
|
|
Assert.IsNotNull(delayedTask);
|
|
Assert.AreEqual(delay, delayedTask.Delay);
|
|
Assert.IsFalse(delayedTask.IsRunning);
|
|
Assert.IsFalse(delayedTask.IsWaitingToRun);
|
|
Assert.IsNull(delayedTask.Exception);
|
|
Assert.AreEqual(1, executionCount);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void ShouldRunOnceAfterReset()
|
|
{
|
|
// arrange
|
|
int executionCount = 0;
|
|
var delay = TimeSpan.FromMilliseconds(100);
|
|
var action = () => { executionCount++; };
|
|
|
|
// act
|
|
var cts = new CancellationTokenSource(delay.Add(TimeSpan.FromSeconds(1)));
|
|
var delayedTask = DelayedTask.Create(action, delay);
|
|
delayedTask.Reset();
|
|
SpinWait.SpinUntil(() => executionCount > 0 || cts.IsCancellationRequested);
|
|
|
|
// assert
|
|
Assert.IsNotNull(delayedTask);
|
|
Assert.AreEqual(delay, delayedTask.Delay);
|
|
Assert.IsFalse(delayedTask.IsRunning);
|
|
Assert.IsFalse(delayedTask.IsWaitingToRun);
|
|
Assert.IsNull(delayedTask.Exception);
|
|
Assert.AreEqual(1, executionCount);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void ShouldCancelWaitingTask()
|
|
{
|
|
// arrange
|
|
int executionCount = 0;
|
|
var delay = TimeSpan.FromMilliseconds(100);
|
|
var action = () => { executionCount++; };
|
|
|
|
// act
|
|
var cts = new CancellationTokenSource(delay.Add(TimeSpan.FromSeconds(1)));
|
|
var delayedTask = DelayedTask.Run(action, delay);
|
|
delayedTask.Cancel();
|
|
SpinWait.SpinUntil(() => executionCount > 0 || cts.IsCancellationRequested);
|
|
|
|
// assert
|
|
Assert.IsNotNull(delayedTask);
|
|
Assert.AreEqual(delay, delayedTask.Delay);
|
|
Assert.IsFalse(delayedTask.IsRunning);
|
|
Assert.IsFalse(delayedTask.IsWaitingToRun);
|
|
Assert.IsNull(delayedTask.Exception);
|
|
Assert.AreEqual(0, executionCount);
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task ShouldResetRunningDelay()
|
|
{
|
|
// arrange
|
|
int executionCount = 0;
|
|
var sw = new Stopwatch();
|
|
|
|
var delay = TimeSpan.FromMilliseconds(200);
|
|
var action = () => { sw.Stop(); executionCount++; };
|
|
|
|
// act
|
|
var cts = new CancellationTokenSource(delay.Add(TimeSpan.FromSeconds(1)));
|
|
sw.Start();
|
|
var delayedTask = DelayedTask.Run(action, delay);
|
|
await Task.Delay(50);
|
|
delayedTask.Reset();
|
|
SpinWait.SpinUntil(() => executionCount > 0 || cts.IsCancellationRequested);
|
|
|
|
// assert
|
|
Assert.IsNotNull(delayedTask);
|
|
Assert.AreEqual(delay, delayedTask.Delay);
|
|
Assert.IsFalse(delayedTask.IsRunning);
|
|
Assert.IsFalse(delayedTask.IsWaitingToRun);
|
|
Assert.IsNull(delayedTask.Exception);
|
|
Assert.AreEqual(1, executionCount);
|
|
// delta of 60ms as the precision below 50ms is really bad for System.Timer
|
|
Assert.AreEqual(250, sw.ElapsedMilliseconds, 60);
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task ShouldNotExecutedImmediateOnCreated()
|
|
{
|
|
// arrange
|
|
int executionCount = 0;
|
|
var sw = new Stopwatch();
|
|
|
|
var delay = TimeSpan.FromMilliseconds(200);
|
|
var action = () => { sw.Stop(); executionCount++; };
|
|
|
|
// act
|
|
var cts = new CancellationTokenSource(delay.Add(TimeSpan.FromSeconds(1)));
|
|
sw.Start();
|
|
var delayedTask = DelayedTask.Create(action, delay);
|
|
await Task.Delay(50);
|
|
bool isSuccess = delayedTask.ExecutePending();
|
|
SpinWait.SpinUntil(() => executionCount > 0 || cts.IsCancellationRequested);
|
|
sw.Stop();
|
|
|
|
// assert
|
|
Assert.IsNotNull(delayedTask);
|
|
Assert.AreEqual(delay, delayedTask.Delay);
|
|
Assert.IsFalse(delayedTask.IsRunning);
|
|
Assert.IsFalse(delayedTask.IsWaitingToRun);
|
|
Assert.IsNull(delayedTask.Exception);
|
|
Assert.AreEqual(0, executionCount);
|
|
// delta of 60ms as the precision below 50ms is really bad for System.Timer
|
|
Assert.AreEqual(1250, sw.ElapsedMilliseconds, 60);
|
|
Assert.IsFalse(isSuccess);
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task ShouldExecuteImmediateOnExecutePendingWhenRunning()
|
|
{
|
|
// arrange
|
|
int executionCount = 0;
|
|
var sw = new Stopwatch();
|
|
|
|
var delay = TimeSpan.FromMilliseconds(200);
|
|
var action = () => { sw.Stop(); executionCount++; };
|
|
|
|
// act
|
|
var cts = new CancellationTokenSource(delay.Add(TimeSpan.FromSeconds(1)));
|
|
sw.Start();
|
|
var delayedTask = DelayedTask.Run(action, delay);
|
|
await Task.Delay(50);
|
|
bool isSuccess = delayedTask.ExecutePending();
|
|
SpinWait.SpinUntil(() => executionCount > 0 || cts.IsCancellationRequested);
|
|
|
|
// assert
|
|
Assert.IsNotNull(delayedTask);
|
|
Assert.AreEqual(delay, delayedTask.Delay);
|
|
Assert.IsFalse(delayedTask.IsRunning);
|
|
Assert.IsFalse(delayedTask.IsWaitingToRun);
|
|
Assert.IsNull(delayedTask.Exception);
|
|
Assert.AreEqual(1, executionCount);
|
|
// delta of 60ms as the precision below 50ms is really bad for System.Timer
|
|
Assert.AreEqual(50, sw.ElapsedMilliseconds, 60);
|
|
Assert.IsTrue(isSuccess);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void ShouldReturnAnAwaiter()
|
|
{
|
|
// arrange
|
|
int executionCount = 0;
|
|
var delay = TimeSpan.FromMilliseconds(100);
|
|
var action = () => { executionCount++; };
|
|
var delayedTask = DelayedTask.Create(action, delay);
|
|
|
|
// act
|
|
delayedTask.Reset();
|
|
var awaiter = delayedTask.GetAwaiter();
|
|
SpinWait.SpinUntil(() => awaiter.IsCompleted);
|
|
|
|
// assert
|
|
Assert.IsNotNull(delayedTask);
|
|
Assert.IsNotNull(awaiter);
|
|
Assert.IsFalse(delayedTask.IsRunning);
|
|
Assert.IsFalse(delayedTask.IsWaitingToRun);
|
|
Assert.IsNull(delayedTask.Exception);
|
|
Assert.AreEqual(1, executionCount);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void ShouldHaveAnExceptionSet()
|
|
{
|
|
// arrange
|
|
var delay = TimeSpan.FromMilliseconds(100);
|
|
var action = () => { throw new Exception("TEST :D"); };
|
|
|
|
// act
|
|
var delayedTask = DelayedTask.Run(action, delay);
|
|
|
|
var awaiter = delayedTask.GetAwaiter();
|
|
SpinWait.SpinUntil(() => awaiter.IsCompleted);
|
|
|
|
// assert
|
|
Assert.IsNotNull(delayedTask);
|
|
Assert.IsFalse(delayedTask.IsRunning);
|
|
Assert.IsFalse(delayedTask.IsWaitingToRun);
|
|
Assert.IsNotNull(delayedTask.Exception);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void ShouldUseExceptionHandler()
|
|
{
|
|
// arrange
|
|
string exceptionText = null;
|
|
var delay = TimeSpan.FromMilliseconds(100);
|
|
var action = () => { throw new Exception("TEST :D"); };
|
|
var exceptionHandler = (Exception ex) =>
|
|
{
|
|
exceptionText = ex.Message;
|
|
};
|
|
|
|
// act
|
|
var delayedTask = DelayedTask.Run(action, delay)
|
|
.WithExceptionHandler(exceptionHandler);
|
|
|
|
var awaiter = delayedTask.GetAwaiter();
|
|
SpinWait.SpinUntil(() => awaiter.IsCompleted);
|
|
|
|
// assert
|
|
Assert.IsNotNull(delayedTask);
|
|
Assert.IsFalse(delayedTask.IsRunning);
|
|
Assert.IsFalse(delayedTask.IsWaitingToRun);
|
|
Assert.IsNotNull(delayedTask.Exception);
|
|
Assert.AreEqual("TEST :D", exceptionText);
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task ShouldReturnNormalTask()
|
|
{
|
|
// arrange
|
|
int executionCount = 0;
|
|
var delay = TimeSpan.FromMilliseconds(100);
|
|
var action = () => { executionCount++; };
|
|
var delayedTask = DelayedTask.Create(action, delay);
|
|
|
|
// act
|
|
delayedTask.Reset();
|
|
var task = delayedTask.Task;
|
|
await task;
|
|
|
|
// assert
|
|
Assert.IsNotNull(delayedTask);
|
|
Assert.IsNotNull(task);
|
|
Assert.IsInstanceOfType(task, typeof(Task));
|
|
Assert.IsFalse(delayedTask.IsRunning);
|
|
Assert.IsFalse(delayedTask.IsWaitingToRun);
|
|
Assert.AreEqual(1, executionCount);
|
|
Assert.AreEqual(TaskStatus.RanToCompletion, task.Status);
|
|
}
|
|
}
|
|
}
|