using System;
using System.Collections;
using NUnit.Framework;
namespace GamesLab.Test
{
///
/// Test the continuation-based Kernel.
///
[TestFixture]
public class TestContinuation
{
///
/// test that we can start then terminate.
///
class TestTerminateClass : ContinuationBase
{
public TestTerminateClass(Kernel kernel) : base(kernel) { }
public int Called;
public override IEnumerator Step()
{
Called++;
yield return 0; // this is how you say "return for now; continue on after this next time"
Called++;
yield return 0;
Called++;
End();
yield return 0;
// should never get here, as we terminated above
Called++;
yield return 0;
}
}
[Test]
public void TestTerminate()
{
var kernel = new Kernel();
var proc = new TestTerminateClass(kernel);
Assert.True(proc.Running);
Assert.True(kernel.NumContinuations == 0);
kernel.Step();
Assert.True(kernel.NumContinuations == 1);
Assert.AreEqual(1, proc.Called);
kernel.Step();
Assert.AreEqual(2, proc.Called);
kernel.Step();
Assert.AreEqual(3, proc.Called);
kernel.Step();
Assert.True(proc.Deleted);
Assert.True(kernel.NumContinuations == 0);
kernel.Step();
kernel.Step();
kernel.Step();
Assert.AreEqual(3, proc.Called);
}
///
/// test that we can start a child continuation
///
class TestChildContinuationClass : ContinuationBase
{
public TestChildContinuationClass(Kernel kernel) : base(kernel) { }
public Continuation ChildContinuation;
public override IEnumerator Step()
{
ChildContinuation = StartChild(Child);
yield return 0;
End();
}
public int ChildCalled;
IEnumerator Child()
{
ChildCalled++;
yield break; // this is how you say "return for now; start again from the beginning next time"
}
}
[Test]
public void TestChildContinuation()
{
var kernel = new Kernel();
var proc = new TestChildContinuationClass(kernel);
Assert.True(proc.Running);
Assert.AreEqual(0, proc.ChildCalled);
kernel.Step();
Assert.True(proc.ChildContinuation.Running);
Assert.AreEqual(1, proc.ChildCalled);
kernel.Step();
Assert.AreEqual(2, proc.ChildCalled);
// on this step, the parent terminates
kernel.Step();
Assert.True(proc.Deleted);
Assert.True(proc.ChildContinuation.Deleted);
// run for a while longer; nothing should be happening
for (var n = 0; n < 42; ++n)
kernel.Step();
Assert.AreEqual(2, proc.ChildCalled);
}
///
/// test that we can create a child continuation, then terminate it.
///
class TestChildTerminateClass : ContinuationBase
{
public TestChildTerminateClass(Kernel kernel) : base(kernel) { }
private Continuation _child;
public override IEnumerator Step()
{
_child = StartChild(Child);
yield return 0;
yield return 0;
_child.Terminate();
yield return 0;
}
public int ChildCalled;
IEnumerator Child()
{
ChildCalled++;
yield break;
}
}
[Test]
public void TestChildTerminate()
{
var kernel = new Kernel();
var proc = new TestChildTerminateClass(kernel);
kernel.Step();
Assert.AreEqual(1, kernel.NumContinuations);
Assert.AreEqual(1, proc.ChildCalled);
Assert.AreEqual(1, proc.Children.Count);
kernel.Step();
Assert.AreEqual(2, proc.ChildCalled);
kernel.Step();
Assert.AreEqual(3, proc.ChildCalled);
Assert.AreEqual(1, proc.Children.Count);
kernel.Step();
Assert.AreEqual(0, proc.Children.Count);
Assert.AreEqual(3, proc.ChildCalled);
}
///
/// Test that we can start a child continuation, suspend it, then resume it.
///
class TestChildSuspendClass : ContinuationBase
{
public TestChildSuspendClass(Kernel kernel) : base(kernel) { }
private Continuation _child;
public int ChildCalled;
public override IEnumerator Step()
{
_child = StartChild(Child);
yield return 0;
_child.Suspend();
yield return 0;
yield return 0;
_child.Resume();
yield return 0;
End();
}
private IEnumerator Child()
{
ChildCalled++;
yield break;
}
}
[Test]
public void TestChildSuspend()
{
var kernel = new Kernel();
var proc = new TestChildSuspendClass(kernel);
// create the child
kernel.Step();
// on the next step, the child should be invoked
kernel.Step();
Assert.AreEqual(1, proc.ChildCalled);
// suspend the child
kernel.Step();
Assert.AreEqual(1, proc.ChildCalled);
// start it again
kernel.Step();
Assert.AreEqual(2, proc.ChildCalled);
// terminate
kernel.Step();
Assert.AreEqual(3, proc.ChildCalled);
// ensure more steps do nothing
for (var n = 0; n < 42; ++n)
kernel.Step();
kernel.Step();
Assert.AreEqual(3, proc.ChildCalled);
}
class TestWaitClass : ContinuationBase
{
public TestWaitClass(Kernel k) : base(k)
{
}
public bool Called;
public override IEnumerator Step()
{
WaitNSeconds(1);
yield return 0;
Called = true;
yield return 0;
}
}
[Test]
public void TestWait()
{
var kernel = new Kernel();
var proc = new TestWaitClass(kernel);
var start = kernel.ZuluTime;
kernel.Step();
while (kernel.ZuluTime < start + new TimeSpan(0, 0, 1))
{
kernel.Step();
}
Assert.True(proc.Called);
}
}
}
//EOF