|
|
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 RunnableComponentTests {
|
|
|
|
|
|
static void ShouldThrow(Action action) {
|
|
|
try {
|
|
|
action();
|
|
|
Assert.Fail();
|
|
|
} catch (AssertFailedException) {
|
|
|
throw;
|
|
|
} catch {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[TestMethod]
|
|
|
public void NormalFlowTest() {
|
|
|
var comp = new MockRunnableComponent(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 InitFailTest() {
|
|
|
var comp = new MockRunnableComponent(false) {
|
|
|
MockInit = () => {
|
|
|
throw new Exception("BAD");
|
|
|
}
|
|
|
};
|
|
|
|
|
|
ShouldThrow(() => comp.Start());
|
|
|
ShouldThrow(() => comp.Stop());
|
|
|
Assert.AreEqual(ExecutionState.Created, comp.State);
|
|
|
|
|
|
ShouldThrow(comp.Initialize);
|
|
|
|
|
|
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 MockRunnableComponent(false);
|
|
|
comp.Dispose();
|
|
|
|
|
|
ShouldThrow(() => comp.Start());
|
|
|
ShouldThrow(() => comp.Stop());
|
|
|
ShouldThrow(comp.Initialize);
|
|
|
|
|
|
Assert.AreEqual(ExecutionState.Disposed, comp.State);
|
|
|
}
|
|
|
|
|
|
[TestMethod]
|
|
|
public void ShouldCallDisposeOnStop() {
|
|
|
var comp = new MockRunnableComponent(true);
|
|
|
|
|
|
bool disposed = false;
|
|
|
comp.MockDispose = (disposing) => {
|
|
|
disposed = true;
|
|
|
};
|
|
|
|
|
|
comp.Start().Join(1000);
|
|
|
comp.Stop().Join(1000);
|
|
|
|
|
|
ShouldThrow(() => comp.Start());
|
|
|
ShouldThrow(() => comp.Stop());
|
|
|
ShouldThrow(comp.Initialize);
|
|
|
|
|
|
Assert.AreEqual(ExecutionState.Disposed, comp.State);
|
|
|
Assert.IsTrue(disposed);
|
|
|
}
|
|
|
|
|
|
[TestMethod]
|
|
|
public void ShouldNotCallDisposeOnStop() {
|
|
|
var comp = new MockRunnableComponent(true, true);
|
|
|
|
|
|
bool disposed = false;
|
|
|
comp.MockDispose = (disposing) => {
|
|
|
disposed = true;
|
|
|
};
|
|
|
|
|
|
comp.Start().Join(1000);
|
|
|
comp.Stop().Join(1000);
|
|
|
|
|
|
Assert.AreEqual(ExecutionState.Ready, comp.State);
|
|
|
Assert.IsFalse(disposed);
|
|
|
}
|
|
|
|
|
|
[TestMethod]
|
|
|
public void SelfDisposeOnStop() {
|
|
|
var comp = new MockRunnableComponent(true, true);
|
|
|
|
|
|
bool disposed = false;
|
|
|
comp.MockDispose = (disposing) => {
|
|
|
disposed = true;
|
|
|
};
|
|
|
|
|
|
comp.Start().Join(1000);
|
|
|
comp.Stop().Join(1000);
|
|
|
|
|
|
Assert.AreEqual(ExecutionState.Ready, comp.State);
|
|
|
Assert.IsFalse(disposed);
|
|
|
|
|
|
comp.MockStop = () => {
|
|
|
comp.Dispose();
|
|
|
return Promise.Success;
|
|
|
};
|
|
|
|
|
|
comp.Start().Join(1000);
|
|
|
comp.Stop().Join(1000);
|
|
|
|
|
|
Assert.AreEqual(ExecutionState.Disposed, comp.State);
|
|
|
Assert.IsTrue(disposed);
|
|
|
}
|
|
|
|
|
|
[TestMethod]
|
|
|
public void StartCancelTest() {
|
|
|
var comp = new MockRunnableComponent(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.IsTrue(comp.LastError is OperationCanceledException);
|
|
|
|
|
|
comp.Dispose();
|
|
|
}
|
|
|
|
|
|
[TestMethod]
|
|
|
public void StartStopTest() {
|
|
|
var stop = new Signal();
|
|
|
var comp = new MockRunnableComponent(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 MockRunnableComponent(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 MockRunnableComponent(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.IsTrue(comp.LastError is OperationCanceledException);
|
|
|
|
|
|
comp.Dispose();
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|