Codex introduction. Base process tidy.
This commit is contained in:
@@ -0,0 +1,170 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Sarand.Net.Standard.Base.Procs;
|
||||
using Sarand.Net.Standard.Base.Tasks;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Sacs.UnitTests.Net.Standard.Base.Procs
|
||||
{
|
||||
//=======================================================================
|
||||
[TestClass]
|
||||
public class SaProcess_Base_Tester
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
private class TestProcessConfig : SaProcess_Base.Config
|
||||
{
|
||||
public TestProcessConfig()
|
||||
{
|
||||
AllowInterruption = true;
|
||||
ConfirmInterruption = false;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
private class TestProcess : SaProcess_Base
|
||||
{
|
||||
public TestProcess(bool stopOnCancellation) : base(new TestProcessConfig())
|
||||
{
|
||||
StopOnCancellation = stopOnCancellation;
|
||||
}
|
||||
|
||||
public override String ProcessDescription { get { return "Test process"; } }
|
||||
public ManualResetEventSlim Started { get; } = new ManualResetEventSlim(false);
|
||||
public ManualResetEventSlim Release { get; } = new ManualResetEventSlim(false);
|
||||
public bool CancellationObserved { get; private set; }
|
||||
private bool StopOnCancellation { get; }
|
||||
|
||||
protected override bool Run()
|
||||
{
|
||||
Started.Set();
|
||||
while (!Release.Wait(5))
|
||||
{
|
||||
if (StopOnCancellation && IsInterrupted)
|
||||
{
|
||||
CancellationObserved = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
[TestMethod]
|
||||
public async Task RunAsync_CompletesAndClearsAsyncState()
|
||||
{
|
||||
using (TestProcess process = new TestProcess(false))
|
||||
{
|
||||
Task runTask = process.RunAsync();
|
||||
Assert.IsTrue(process.Started.Wait(1000), "Process did not start.");
|
||||
Assert.IsTrue(process.IsAsync);
|
||||
|
||||
process.Release.Set();
|
||||
await runTask;
|
||||
|
||||
Assert.IsFalse(process.IsAsync);
|
||||
Assert.IsFalse(process.Processing);
|
||||
Assert.IsTrue(process.ProcessEnded);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
[TestMethod]
|
||||
public async Task RunAsync_RejectsOverlappingRun()
|
||||
{
|
||||
using (TestProcess process = new TestProcess(false))
|
||||
{
|
||||
Task runTask = process.RunAsync();
|
||||
Assert.IsTrue(process.Started.Wait(1000), "Process did not start.");
|
||||
|
||||
await Assert.ThrowsExceptionAsync<SaProcess_Base.InProgressException>(() => process.RunAsync());
|
||||
|
||||
process.Release.Set();
|
||||
await runTask;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
[TestMethod]
|
||||
public async Task StopProcessAsync_TimeoutRetainsAsyncState()
|
||||
{
|
||||
using (TestProcess process = new TestProcess(false))
|
||||
{
|
||||
Task runTask = process.RunAsync();
|
||||
Assert.IsTrue(process.Started.Wait(1000), "Process did not start.");
|
||||
|
||||
Assert.IsFalse(await process.StopProcessAsync(40));
|
||||
Assert.IsTrue(process.IsAsync, "A timed-out stop must retain the active process state.");
|
||||
await Assert.ThrowsExceptionAsync<SaProcess_Base.InProgressException>(() => process.RunAsync());
|
||||
|
||||
process.Release.Set();
|
||||
await runTask;
|
||||
Assert.IsFalse(process.IsAsync);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
[TestMethod]
|
||||
public async Task StopProcessAsync_CooperativeCancellationStopsProcess()
|
||||
{
|
||||
using (TestProcess process = new TestProcess(true))
|
||||
{
|
||||
Task runTask = process.RunAsync();
|
||||
Assert.IsTrue(process.Started.Wait(1000), "Process did not start.");
|
||||
|
||||
Assert.IsTrue(await process.StopProcessAsync(1000));
|
||||
await runTask;
|
||||
|
||||
Assert.IsTrue(process.CancellationObserved);
|
||||
Assert.IsFalse(process.IsAsync);
|
||||
Assert.IsTrue(await process.StopProcessAsync(20), "Stopping an idle process should succeed.");
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
[TestMethod]
|
||||
public async Task StopProcessAsync_CancellationCallbackCanReadAsyncState()
|
||||
{
|
||||
using (TestProcess process = new TestProcess(true))
|
||||
{
|
||||
Task runTask = process.RunAsync();
|
||||
Assert.IsTrue(process.Started.Wait(1000), "Process did not start.");
|
||||
|
||||
CancellationToken cancellationToken = GetCancellationToken(process);
|
||||
bool callbackInvoked = false;
|
||||
using (cancellationToken.Register(() =>
|
||||
{
|
||||
callbackInvoked = true;
|
||||
Assert.IsTrue(process.IsAsync);
|
||||
}))
|
||||
{
|
||||
Task<bool> stopTask = process.StopProcessAsync(1000);
|
||||
Task completedTask = await Task.WhenAny(stopTask, Task.Delay(2000));
|
||||
Assert.AreSame(stopTask, completedTask, "Cancellation callback deadlocked on the lifecycle lock.");
|
||||
Assert.IsTrue(await stopTask);
|
||||
}
|
||||
|
||||
await runTask;
|
||||
Assert.IsTrue(callbackInvoked);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
private static CancellationToken GetCancellationToken(SaProcess_Base process)
|
||||
{
|
||||
PropertyInfo controlProperty = typeof(SaProcess_Base).GetProperty("Control", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
Assert.IsNotNull(controlProperty);
|
||||
Object control = controlProperty.GetValue(process);
|
||||
Assert.IsNotNull(control);
|
||||
|
||||
PropertyInfo taskDataProperty = control.GetType().GetProperty("TaskData", BindingFlags.Instance | BindingFlags.Public);
|
||||
Assert.IsNotNull(taskDataProperty);
|
||||
SacsTaskData taskData = (SacsTaskData)taskDataProperty.GetValue(control);
|
||||
Assert.IsNotNull(taskData);
|
||||
return taskData.CancellationToken;
|
||||
}
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
Reference in New Issue
Block a user