|
|
using System;
|
|
|
using System.Reflection;
|
|
|
using System.Threading;
|
|
|
using Implab.Parallels;
|
|
|
using Implab.Components;
|
|
|
|
|
|
#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 RunnableComponentTests {
|
|
|
|
|
|
static void ShouldThrow(Action action) {
|
|
|
try {
|
|
|
action();
|
|
|
Assert.Fail();
|
|
|
} catch (AssertFailedException) {
|
|
|
throw;
|
|
|
} catch {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
class Runnable : RunnableComponent {
|
|
|
public Runnable(bool initialized) : base(initialized) {
|
|
|
}
|
|
|
|
|
|
public Action MockInit {
|
|
|
get;
|
|
|
set;
|
|
|
}
|
|
|
|
|
|
public Func<IPromise> MockStart {
|
|
|
get;
|
|
|
set;
|
|
|
}
|
|
|
|
|
|
public Func<IPromise> MockStop {
|
|
|
get;
|
|
|
set;
|
|
|
}
|
|
|
|
|
|
protected override IPromise OnStart() {
|
|
|
return MockStart != null ? MockStart() : base.OnStart();
|
|
|
}
|
|
|
|
|
|
protected override IPromise OnStop() {
|
|
|
return MockStop != null ? MockStop() : base.OnStart();
|
|
|
}
|
|
|
|
|
|
protected override void OnInitialize() {
|
|
|
if (MockInit != null)
|
|
|
MockInit();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
[TestMethod]
|
|
|
public void NormalFlowTest() {
|
|
|
var comp = new Runnable(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 InitFailTest() {
|
|
|
var comp = new Runnable(false) {
|
|
|
MockInit = () => {
|
|
|
throw new Exception("BAD");
|
|
|
}
|
|
|
};
|
|
|
|
|
|
ShouldThrow(() => comp.Start());
|
|
|
ShouldThrow(() => comp.Stop());
|
|
|
Assert.AreEqual(ExecutionState.Created, comp.State);
|
|
|
|
|
|
ShouldThrow(comp.Init);
|
|
|
|
|
|
Assert.AreEqual(ExecutionState.Failed, comp.State);
|
|
|
|
|
|
ShouldThrow(() => comp.Start());
|
|
|
ShouldThrow(() => comp.Stop());
|
|
|
Assert.AreEqual(ExecutionState.Failed, comp.State);
|
|
|
|
|
|
comp.Dispose();
|
|
|
Assert.AreEqual(ExecutionState.Disposed, comp.State);
|
|
|
}
|
|
|
|
|
|
[TestMethod]
|
|
|
public void DisposedTest() {
|
|
|
|
|
|
var comp = new Runnable(false);
|
|
|
comp.Dispose();
|
|
|
|
|
|
ShouldThrow(() => comp.Start());
|
|
|
ShouldThrow(() => comp.Stop());
|
|
|
ShouldThrow(comp.Init);
|
|
|
|
|
|
Assert.AreEqual(ExecutionState.Disposed, comp.State);
|
|
|
}
|
|
|
|
|
|
[TestMethod]
|
|
|
public void StartCancelTest() {
|
|
|
var comp = new Runnable(true) {
|
|
|
MockStart = () => PromiseHelper.Sleep(100000, 0)
|
|
|
};
|
|
|
|
|
|
var p = comp.Start();
|
|
|
Assert.AreEqual(ExecutionState.Starting, comp.State);
|
|
|
p.Cancel();
|
|
|
ShouldThrow(() => p.Join(1000));
|
|
|
Assert.AreEqual(ExecutionState.Failed, comp.State);
|
|
|
|
|
|
Assert.IsInstanceOfType(comp.LastError, typeof(OperationCanceledException));
|
|
|
|
|
|
comp.Dispose();
|
|
|
}
|
|
|
|
|
|
[TestMethod]
|
|
|
public void StartStopTest() {
|
|
|
var stop = new Signal();
|
|
|
var comp = new Runnable(true) {
|
|
|
MockStart = () => PromiseHelper.Sleep(100000, 0),
|
|
|
MockStop = () => AsyncPool.RunThread(stop.Wait)
|
|
|
};
|
|
|
|
|
|
var p1 = comp.Start();
|
|
|
var p2 = comp.Stop();
|
|
|
// should enter stopping state
|
|
|
|
|
|
ShouldThrow(p1.Join);
|
|
|
Assert.IsTrue(p1.IsCancelled);
|
|
|
Assert.AreEqual(ExecutionState.Stopping, comp.State);
|
|
|
|
|
|
stop.Set();
|
|
|
p2.Join(1000);
|
|
|
Assert.AreEqual(ExecutionState.Disposed, comp.State);
|
|
|
}
|
|
|
|
|
|
[TestMethod]
|
|
|
public void StartStopFailTest() {
|
|
|
var comp = new Runnable(true) {
|
|
|
MockStart = () => PromiseHelper.Sleep(100000, 0).Then(null,null,x => { throw new Exception("I'm dead"); })
|
|
|
};
|
|
|
|
|
|
comp.Start();
|
|
|
var p = comp.Stop();
|
|
|
// if Start fails to cancel, should fail to stop
|
|
|
ShouldThrow(() => p.Join(1000));
|
|
|
Assert.AreEqual(ExecutionState.Failed, comp.State);
|
|
|
Assert.IsNotNull(comp.LastError);
|
|
|
Assert.AreEqual("I'm dead", comp.LastError.Message);
|
|
|
}
|
|
|
|
|
|
[TestMethod]
|
|
|
public void StopCancelTest() {
|
|
|
var comp = new Runnable(true) {
|
|
|
MockStop = () => PromiseHelper.Sleep(100000, 0)
|
|
|
};
|
|
|
|
|
|
comp.Start();
|
|
|
var p = comp.Stop();
|
|
|
Assert.AreEqual(ExecutionState.Stopping, comp.State);
|
|
|
p.Cancel();
|
|
|
ShouldThrow(() => p.Join(1000));
|
|
|
Assert.AreEqual(ExecutionState.Failed, comp.State);
|
|
|
Assert.IsInstanceOfType(comp.LastError, typeof(OperationCanceledException));
|
|
|
|
|
|
comp.Dispose();
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|