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