Mercurial > pub > ImplabNet
diff Implab.Test/RunnableComponentTests.cs @ 262:f1696cdc3d7a v3 v3.0.8
Added IInitializable.Initialize() overload
Added IRunnable.Start(), IRunnable.Start() overloads
Fixed cancellation of the current operation when Stop() is called
More tests
author | cin |
---|---|
date | Mon, 16 Apr 2018 02:12:39 +0300 |
parents | 547a2fc0d93e |
children |
line wrap: on
line diff
--- a/Implab.Test/RunnableComponentTests.cs Fri Apr 13 19:15:11 2018 +0300 +++ b/Implab.Test/RunnableComponentTests.cs Mon Apr 16 02:12:39 2018 +0300 @@ -8,7 +8,7 @@ public class RunnableComponentTests { [Fact] - public async Task Test1() { + public async Task SimpleStartStop() { using (var m = new MockPollComponent(true)) { m.StartWorker = async (ct) => await Task.Yield(); @@ -16,12 +16,246 @@ Assert.Equal(ExecutionState.Ready, m.State); Assert.NotNull(m.Completion); - - m.Start(CancellationToken.None); + + m.Start(); await m.Completion; Assert.Equal(ExecutionState.Running, m.State); + m.Stop(); + await m.Completion; + Assert.Equal(ExecutionState.Stopped, m.State); + } + } + + [Fact] + public async Task SyncStart() { + using (var m = new MockPollComponent(true)) { + m.Start(); + Assert.Equal(ExecutionState.Running, m.State); + await m.Completion; + } + } + + [Fact] + public async Task AsyncStarting() { + using (var m = new MockPollComponent(true)) { + var signal = Safe.CreateTask(); + + m.StartWorker = async (ct) => await signal; + m.Start(); + + Assert.Equal(ExecutionState.Starting, m.State); + Assert.False(m.Completion.IsCompleted); + + signal.Start(); + + await m.Completion; + + Assert.Equal(ExecutionState.Running, m.State); + } + } + + [Fact] + public async Task FailWhileStarting() { + using (var m = new MockPollComponent(true)) { + const string failMessage = "Fail me"; + var signal = new Task(() => { + throw new Exception(failMessage); + }); + + m.StartWorker = async (ct) => await signal; + m.Start(); + + Assert.Equal(ExecutionState.Starting, m.State); + Assert.False(m.Completion.IsCompleted); + + signal.Start(); + try { + await m.Completion; + Assert.True(false); + } catch (Exception e) { + Assert.Equal(failMessage, e.Message); + } + + Assert.Equal(ExecutionState.Failed, m.State); + } + } + + [Fact] + public async Task SyncStop() { + using (var m = new MockPollComponent(true)) { + m.Start(); + Assert.Equal(ExecutionState.Running, m.State); + m.Stop(); + Assert.Equal(ExecutionState.Stopped, m.State); + await m.Completion; + } + } + + [Fact] + public async Task AsyncStopping() { + using (var m = new MockPollComponent(true)) { + var signal = Safe.CreateTask(); + + m.StopWorker = async (ct) => await signal; + + // Start + m.Start(); + Assert.Equal(ExecutionState.Running, m.State); + + // Stop + m.Stop(); + Assert.Equal(ExecutionState.Stopping, m.State); + Assert.False(m.Completion.IsCompleted); + signal.Start(); + + await m.Completion; + + Assert.Equal(ExecutionState.Stopped, m.State); + } + } + + [Fact] + public async Task FailWhileStopping() { + using (var m = new MockPollComponent(true)) { + const string failMessage = "Fail me"; + var signal = new Task(() => { + throw new Exception(failMessage); + }); + + m.StopWorker = async (ct) => await signal; + + // Start + m.Start(); + Assert.Equal(ExecutionState.Running, m.State); + + // Stop + m.Stop(); + Assert.Equal(ExecutionState.Stopping, m.State); + Assert.False(m.Completion.IsCompleted); + + signal.Start(); + try { + await m.Completion; + Assert.True(false); + } catch (Exception e) { + Assert.Equal(failMessage, e.Message); + } + + Assert.Equal(ExecutionState.Failed, m.State); + } + } + + [Fact] + public async Task ThrowOnInvalidTrasition() { + using (var m = new MockPollComponent(false)) { + var started = Safe.CreateTask(); + var stopped = Safe.CreateTask(); + + m.StartWorker = async (ct) => await started; + m.StopWorker = async (ct) => await stopped; + + Assert.Throws<InvalidOperationException>(() => m.Start()); + + // Initialize + m.Initialize(); + await m.Completion; + + // Start + m.Start(); + Assert.Equal(ExecutionState.Starting, m.State); + + // Check invalid transitions + Assert.Throws<InvalidOperationException>(() => m.Start()); + + // Component can be stopped before started + // m.Stop(CancellationToken.None); + + // Running + started.Start(); + await m.Completion; + Assert.Equal(ExecutionState.Running, m.State); + + + Assert.Throws<InvalidOperationException>(() => m.Start()); + + // Stop + m.Stop(); + + // Check invalid transitions + Assert.Throws<InvalidOperationException>(() => m.Start()); + Assert.Throws<InvalidOperationException>(() => m.Stop()); + + // Stopped + stopped.Start(); + await m.Completion; + Assert.Equal(ExecutionState.Stopped, m.State); + + // Check invalid transitions + Assert.Throws<InvalidOperationException>(() => m.Start()); + Assert.Throws<InvalidOperationException>(() => m.Stop()); + } + } + + [Fact] + public async Task CancelStart() { + using (var m = new MockPollComponent(true)) { + m.StartWorker = (ct) => Safe.CreateTask(ct); + + m.Start(); + var start = m.Completion; + + Assert.Equal(ExecutionState.Starting, m.State); + m.Stop(); + await m.Completion; + Assert.Equal(ExecutionState.Stopped, m.State); + Assert.True(start.IsCompleted); + Assert.True(start.IsCanceled); + } + } + + [Fact] + public async Task AwaitWorker() { + using (var m = new MockPollComponent(true)) { + var worker = Safe.CreateTask(); + + m.PollWorker = (ct) => worker; + + m.Start(CancellationToken.None); + await m.Completion; + + Assert.Equal(ExecutionState.Running, m.State); + m.Stop(CancellationToken.None); + Assert.Equal(ExecutionState.Stopping, m.State); + worker.Start(); + await m.Completion; + Assert.Equal(ExecutionState.Stopped, m.State); + } + } + + [Fact] + public async Task CancelWorker() { + using (var m = new MockPollComponent(true)) { + var worker = Safe.CreateTask(); + + var started = Safe.CreateTask(); + + m.PollWorker = async (ct) => { + started.Start(); + await worker; + ct.ThrowIfCancellationRequested(); + }; + + m.Start(CancellationToken.None); + await m.Completion; + await started; // await for the poll worker to start + + Assert.Equal(ExecutionState.Running, m.State); + + m.Stop(CancellationToken.None); + Assert.Equal(ExecutionState.Stopping, m.State); + worker.Start(); await m.Completion; Assert.Equal(ExecutionState.Stopped, m.State); }