PollingComponentTests.cs
230 lines
| 6.3 KiB
| text/x-csharp
|
CSharpLexer
/ Implab.Test / PollingComponentTests.cs
cin
|
r203 | 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.Init(); | ||||
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); | ||||
} | ||||
} | ||||
} | ||||