using System; using System.Linq; using System.Threading; using Amphora; using UnitTestSharp; namespace Ariadne.UnitTests { public class WaitTests : TestFixture { public static TickContext At(ExceptionSandbox sandbox, double gameSeconds) { return TestTicks.At(sandbox, TimeSpan.FromMilliseconds(16), TimeSpan.FromSeconds(gameSeconds)); } public class RunTests : TestFixture { private ArcTests.Gates gates; private ExceptionSandbox sandbox; public override void TestSetup() { gates = new ArcTests.Gates(); sandbox = TestTicks.NewSandbox(); } public void FirstTick_RunsToTheWaitAndPauses() { var script = new WaitingScript(); script.Tick(gates, At(sandbox, 10)); CheckEqual(new[] { "start" }, script.Log); CheckEqual(new[] { "first" }, script.Cursor); CheckFalse(script.Finished); } public void BeforeTheDeadline_KeepsWaiting() { var script = new WaitingScript(); script.Tick(gates, At(sandbox, 10)); script.Tick(gates, At(sandbox, 10.9)); CheckEqual(new[] { "start" }, script.Log); CheckEqual(new[] { "first" }, script.Cursor); } public void AtTheDeadline_RunsOnToTheNextWait() { var script = new WaitingScript(); script.Tick(gates, At(sandbox, 10)); script.Tick(gates, At(sandbox, 11)); CheckEqual(new[] { "start", "after one second" }, script.Log); CheckEqual(new[] { "second" }, script.Cursor); } public void SecondWait_IsCountedFromWhenItBegan() { var script = new WaitingScript(); script.Tick(gates, At(sandbox, 10)); script.Tick(gates, At(sandbox, 11.5)); script.Tick(gates, At(sandbox, 13)); CheckFalse(script.Finished); script.Tick(gates, At(sandbox, 13.5)); CheckEqual(new[] { "start", "after one second", "end" }, script.Log); CheckTrue(script.Finished); } public void GameTimeStandingStill_NeverFinishes() { var script = new WaitingScript(); for (int i = 0; i < 5; ++i) { script.Tick(gates, At(sandbox, 10)); } CheckEqual(new[] { "start" }, script.Log); } public void GameTimeJumpingPastTheDeadline_RunsOn() { var script = new WaitingScript(); script.Tick(gates, At(sandbox, 10)); script.Tick(gates, At(sandbox, 100)); CheckEqual(new[] { "start", "after one second" }, script.Log); CheckEqual(new[] { "second" }, script.Cursor); } public void SpanOfZeroOrLess_DoesNotPause() { var script = new NoTimeWaitScript(); script.Tick(gates, At(sandbox, 10)); CheckEqual(new[] { "through zero", "through negative" }, script.Log); CheckTrue(script.Finished); } public void WaitInALoop_WaitsEachTrip() { var script = new LoopWaitScript(); script.Tick(gates, At(sandbox, 10)); script.Tick(gates, At(sandbox, 11)); CheckEqual(new[] { "trip 0" }, script.Log); script.Tick(gates, At(sandbox, 12)); script.Tick(gates, At(sandbox, 13)); CheckEqual(new[] { "trip 0", "trip 1", "trip 2" }, script.Log); CheckTrue(script.Finished); } public void GotoToAWaitStep_WaitsAgainFromTheNewTime() { var script = new JumpWaitScript(); script.Tick(gates, At(sandbox, 10)); script.Tick(gates, At(sandbox, 11)); CheckEqual(new[] { "lap 1" }, script.Log); script.Tick(gates, At(sandbox, 11.9)); CheckEqual(new[] { "lap 1" }, script.Log); script.Tick(gates, At(sandbox, 12)); CheckEqual(new[] { "lap 1", "lap 2" }, script.Log); CheckTrue(script.Finished); } public void LongestSpan_WaitsTheLongestFiniteTimeAndRecordsNothing() { var script = new ForeverWaitScript(); script.Tick(gates, At(sandbox, 10)); script.Tick(gates, At(sandbox, 1e9)); CheckEqual(0, sandbox.Entries.Count); CheckEqual(0, script.Log.Count); CheckFalse(script.Finished); } public void InfiniteSpan_NeverWakesAndRecordsNothing() { var script = new SpanWaitScript { Span = Timeout.InfiniteTimeSpan }; script.Tick(gates, At(sandbox, 10)); script.Tick(gates, At(sandbox, 1e9)); CheckEqual(0, script.Log.Count); CheckEqual(0, sandbox.Entries.Count); CheckFalse(script.Finished); CheckEqual(new[] { "rest" }, script.Cursor); } public void ForeverSpan_NeverWakesAndRecordsNothing() { var script = new SpanWaitScript { Span = Duration.Forever }; script.Tick(gates, At(sandbox, 10)); script.Tick(gates, At(sandbox, 1e11)); CheckEqual(0, script.Log.Count); CheckEqual(0, sandbox.Entries.Count); CheckFalse(script.Finished); } public void NegativeForeverSpan_DoesNotPause() { var script = new SpanWaitScript { Span = -Duration.Forever }; script.Tick(gates, At(sandbox, 10)); CheckEqual(new[] { "woke" }, script.Log); CheckTrue(script.Finished); } public void SpanOfMinusTwoMilliseconds_DoesNotPause() { var script = new SpanWaitScript { Span = TimeSpan.FromMilliseconds(-2) }; script.Tick(gates, At(sandbox, 10)); CheckEqual(new[] { "woke" }, script.Log); CheckTrue(script.Finished); } public void WaitInOneBranch_PausesOnlyThere() { var slow = new BranchWaitScript(); gates.Open.Add("slow"); slow.Tick(gates, At(sandbox, 10)); CheckEqual(new[] { "start" }, slow.Log); CheckEqual(new[] { "slow" }, slow.Cursor); slow.Tick(gates, At(sandbox, 11)); CheckEqual(new[] { "start", "slow", "end" }, slow.Log); gates.Open.Remove("slow"); var quick = new BranchWaitScript(); quick.Tick(gates, At(sandbox, 10)); CheckEqual(new[] { "start", "quick", "end" }, quick.Log); CheckTrue(quick.Finished); } public void WaitInAPassageOfAnotherArc_PausesTheCaller() { var client = new WaitClientScript(); client.Tick(gates, At(sandbox, 10)); client.Tick(gates, At(sandbox, 10.5)); CheckEqual(0, client.Worker.Log.Count); CheckFalse(client.Finished); client.Tick(gates, At(sandbox, 11)); CheckEqual(new[] { "rested" }, client.Worker.Log); CheckTrue(client.Finished); } } public class AskTests : TestFixture { private ArcTests.Gates gates; private ExceptionSandbox sandbox; public override void TestSetup() { gates = new ArcTests.Gates(); sandbox = TestTicks.NewSandbox(); } public void PassageCallInTheSpan_PausesUntilItIsDone() { var script = new AskWaitScript(); script.Tick(gates, At(sandbox, 10)); script.Tick(gates, At(sandbox, 11)); CheckEqual(new[] { "first", "ask" }, script.Cursor); CheckEqual(0, script.Log.Count); } public void DeadlineCountsFromWhenTheCallFinishes() { var script = new AskWaitScript(); script.Tick(gates, At(sandbox, 10)); gates.Open.Add("answer"); script.Tick(gates, At(sandbox, 12)); CheckEqual(new[] { "first#1" }, script.Cursor); script.Tick(gates, At(sandbox, 13.9)); CheckEqual(0, script.Log.Count); script.Tick(gates, At(sandbox, 14)); CheckEqual(new[] { "done" }, script.Log); CheckTrue(script.Finished); } public void AnswerThatIsAlreadyThere_WaitsFromTheFirstTick() { gates.Open.Add("answer"); var script = new AskWaitScript(); script.Tick(gates, At(sandbox, 10)); script.Tick(gates, At(sandbox, 11.9)); CheckEqual(0, script.Log.Count); script.Tick(gates, At(sandbox, 12)); CheckEqual(new[] { "done" }, script.Log); } public void TwoCallsAndALocal_AreAddedIntoOneDeadline() { var script = new AskSumWaitScript(); script.Tick(gates, At(sandbox, 10)); gates.Open.Add("a"); script.Tick(gates, At(sandbox, 11)); CheckEqual(new[] { "first#1", "ask" }, script.Cursor); gates.Open.Add("b"); script.Tick(gates, At(sandbox, 12)); script.Tick(gates, At(sandbox, 14.4)); CheckEqual(0, script.Log.Count); script.Tick(gates, At(sandbox, 14.5)); CheckEqual(new[] { "done" }, script.Log); } public void ReloadMidCall_StillWaitsFromWhenTheCallFinishes() { var script = new AskWaitScript(); script.Tick(gates, At(sandbox, 10)); var reloaded = LoadedArc.From(ArcRecord.Of(script)); gates.Open.Add("answer"); reloaded.Tick(gates, At(sandbox, 12)); reloaded.Tick(gates, At(sandbox, 13.9)); CheckEqual(0, reloaded.Log.Count); reloaded.Tick(gates, At(sandbox, 14)); CheckEqual(new[] { "done" }, reloaded.Log); } public void ReloadMidWait_KeepsTheDeadlineTheCallMade() { var script = new AskWaitScript(); gates.Open.Add("answer"); script.Tick(gates, At(sandbox, 12)); var reloaded = LoadedArc.From(ArcRecord.Of(script)); CheckEqual(Duration.FromSeconds(14), ArcRecord.Of(script).Locals["Run.__wait1"]); reloaded.Tick(gates, At(sandbox, 13.9)); CheckEqual(0, reloaded.Log.Count); reloaded.Tick(gates, At(sandbox, 14)); CheckEqual(new[] { "done" }, reloaded.Log); } public void ReloadBetweenTwoCalls_KeepsTheLocalTheSpanReadsAfterBoth() { var script = new AskSumWaitScript(); script.Tick(gates, At(sandbox, 10)); gates.Open.Add("a"); script.Tick(gates, At(sandbox, 11)); var reloaded = LoadedArc.From(ArcRecord.Of(script)); gates.Open.Add("b"); reloaded.Tick(gates, At(sandbox, 12)); reloaded.Tick(gates, At(sandbox, 14.4)); CheckEqual(0, reloaded.Log.Count); reloaded.Tick(gates, At(sandbox, 14.5)); CheckEqual(new[] { "done" }, reloaded.Log); } } public class SaveTests : TestFixture { private ArcTests.Gates gates; private ExceptionSandbox sandbox; public override void TestSetup() { gates = new ArcTests.Gates(); sandbox = TestTicks.NewSandbox(); } public void Deadline_IsSavedAsTheTimeTheWaitBeganPlusItsSpan() { var script = new WaitingScript(); script.Tick(gates, At(sandbox, 10)); ArcRecord record = ArcRecord.Of(script); CheckEqual(new[] { "Run.__wait1" }, record.Locals.Keys.ToArray()); CheckEqual(Duration.FromSeconds(11), record.Locals["Run.__wait1"]); } public void SpanHeldInALocal_IsNotSavedWithTheDeadline() { var script = new SpanLocalScript(); script.Tick(gates, At(sandbox, 10)); CheckEqual(new[] { "Run.__wait1" }, ArcRecord.Of(script).Locals.Keys.ToArray()); } public void DeadlineInAPassageOfAnotherArc_IsSavedAmongTheCallers() { var client = new WaitClientScript(); client.Tick(gates, At(sandbox, 10)); CheckEqual(Duration.FromSeconds(11), ArcRecord.Of(client).AllLocals()["Run.pace/Pace.__wait1"]); } public void ReloadMidWait_KeepsTheDeadline() { var script = new WaitingScript(); script.Tick(gates, At(sandbox, 10)); var reloaded = LoadedArc.From(ArcRecord.Of(script)); reloaded.Tick(gates, At(sandbox, 10.5)); CheckEqual(0, reloaded.Log.Count); reloaded.Tick(gates, At(sandbox, 11)); CheckEqual(new[] { "after one second" }, reloaded.Log); } public void ReloadMidWaitInAnotherArcsPassage_KeepsTheDeadline() { var client = new WaitClientScript(); client.Tick(gates, At(sandbox, 10)); var reloaded = LoadedArc.From(ArcRecord.Of(client)); reloaded.Tick(gates, At(sandbox, 10.5)); CheckFalse(reloaded.Finished); reloaded.Tick(gates, At(sandbox, 11)); CheckTrue(reloaded.Finished); } } public class RestartTests : TestFixture { public void RestartMidWait_TakesANewDeadlineFromTheNewStart() { var gates = new ArcTests.Gates(); ExceptionSandbox sandbox = TestTicks.NewSandbox(); var script = new WaitingScript(); script.Tick(gates, At(sandbox, 10)); script.Restart(); script.Tick(gates, At(sandbox, 20)); script.Tick(gates, At(sandbox, 20.9)); CheckEqual(new[] { "start", "start" }, script.Log); script.Tick(gates, At(sandbox, 21)); CheckEqual(new[] { "start", "start", "after one second" }, script.Log); } } } }