##// END OF EJS Templates
Added ResetState to RunnableComponent to reset in case of failure...
Added ResetState to RunnableComponent to reset in case of failure Added StateChanged event to IRunnable Renamed Promise.SUCCESS -> Promise.Success Added Promise.FromException Renamed Bundle -> PromiseAll in PromiseExtensions

File last commit:

r205:8200ab154c8a v2
r205:8200ab154c8a v2
Show More
PollingComponentTests.cs
230 lines | 6.3 KiB | text/x-csharp | CSharpLexer
/ Implab.Test / PollingComponentTests.cs
using System;
using System.Reflection;
using System.Threading;
using Implab.Parallels;
using Implab.Components;
using Implab.Test.Mock;
#if MONO
using NUnit.Framework;
using TestClassAttribute = NUnit.Framework.TestFixtureAttribute;
using TestMethodAttribute = NUnit.Framework.TestAttribute;
using AssertFailedException = NUnit.Framework.AssertionException;
#else
using Microsoft.VisualStudio.TestTools.UnitTesting;
#endif
namespace Implab.Test {
[TestClass]
public class PollingComponentTests {
static void ShouldThrow(Action action) {
try {
action();
Assert.Fail();
} catch (AssertFailedException) {
throw;
} catch {
}
}
[TestMethod]
public void NormalFlowTest() {
var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, false);
Assert.AreEqual(ExecutionState.Created, comp.State);
comp.Initialize();
Assert.AreEqual(ExecutionState.Ready, comp.State);
comp.Start().Join(1000);
Assert.AreEqual(ExecutionState.Running, comp.State);
comp.Stop().Join(1000);
Assert.AreEqual(ExecutionState.Disposed, comp.State);
}
[TestMethod]
public void ShouldStartTicks() {
var signal = new Signal();
var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true);
comp.MockTick = ct => {
signal.Set();
return Promise.Success;
};
comp.Start().Join(1000);
signal.Wait(1000);
comp.Stop().Join(1000);
}
[TestMethod]
public void StopShouldWaitForTickToComplete() {
var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true);
var signal = new Signal();
var promise = new Promise();
// timer should tick once
comp.MockTick = ct => {
signal.Set();
return promise;
};
// start timer
comp.Start().Join(1000);
signal.Wait(); // wait for tick
// try to stop component
var stopping = comp.Stop();
Assert.AreEqual(ExecutionState.Stopping, comp.State);
ShouldThrow(() => stopping.Join(100));
Assert.AreEqual(ExecutionState.Stopping, comp.State);
// complete operation
promise.Resolve();
// the component should stop normally
stopping.Join(1000);
Assert.AreEqual(ExecutionState.Disposed, comp.State);
}
[TestMethod]
public void ShouldRecoverAfterTickError() {
var ticks = 0;
var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true);
var signal = new Signal(); // will signal when timer fires 10 times
comp.MockTick = ct => {
ticks++;
if (ticks == 10)
signal.Set();
// each time handler dies
throw new Exception("tainted handler");
};
comp.Start();
signal.Wait(1000);
comp.Stop().Join(1000);
Assert.AreEqual(ExecutionState.Disposed, comp.State);
}
[TestMethod]
public void StopCancelHandlerOnStop() {
var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true);
var started = new Signal();
bool cancelled = false;
// timer should tick once
comp.MockTick = ct => {
started.Set();
while(!ct.IsCancellationRequested) {
Thread.Sleep(1);
}
cancelled = true;
throw new OperationCanceledException();
};
// start timer
comp.Start().Join(1000);
started.Wait(); // wait for tick
// try to stop component
comp.Stop().Join(1000);
Assert.AreEqual(true, cancelled);
Assert.AreEqual(ExecutionState.Disposed, comp.State);
}
[TestMethod]
public void FailTickOnStopShouldBeIgnored() {
var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true);
var started = new Signal();
var finish = new Signal();
// timer should tick once
comp.MockTick = ct => {
started.Set();
finish.Wait();
// component is in stopping state here
throw new Exception("Die, die, die!!!");
};
comp.MockOnError = comp.CallComponentFail;
// start timer
comp.Start().Join(1000);
started.Wait(); // wait for tick
// try to stop component
var stopping = comp.Stop();
// the component is in stopping state but it is waiting for the tick handler to complete
finish.Set(); // signal the tick handler to finish
// tick handler should stop rather soon
stopping.Join(1000);
// validate the component is disposed
Assert.AreEqual(ExecutionState.Disposed, comp.State);
}
[TestMethod]
public void FailTickShouldFailComponent() {
var comp = new MockPollingComponent(TimeSpan.FromMilliseconds(1), null, true);
var started = new Signal();
var finish = new Signal();
// timer should tick once
comp.MockTick = ct => {
started.Set();
throw new Exception("Die, die, die!!!");
};
comp.MockOnError = err => {
comp.CallComponentFail(err);
finish.Set();
};
// start timer
comp.Start().Join(1000);
started.Wait(); // wait for tick
finish.Wait();
// try to stop component
ShouldThrow(() => comp.Stop());
Assert.AreEqual(ExecutionState.Failed, comp.State);
Assert.IsNotNull(comp.LastError);
Assert.AreEqual("Die, die, die!!!", comp.LastError.Message);
comp.Dispose();
Assert.AreEqual(ExecutionState.Disposed, comp.State);
}
}
}