using System; using Amphora; using UnitTestSharp; using Vellum; namespace Ariadne.Vellum.UnitTests { /// /// Saves scripts paused on latches, and reloads them into a scheduler of their own. /// public class LatchWaitSaveTests : TestFixture { /// /// A lounge, a scheduler over it, and the ticks that drive them. /// public class Room { public readonly Lounge Lounge; public readonly ArcScheduler Scheduler = new ArcScheduler(); private readonly ExceptionSandbox sandbox = new ExceptionSandbox(typeof(AriadneSites).Assembly); public Room(Lounge lounge) { Lounge = lounge; } public Room() : this(new Lounge()) { } public void TickAt(double gameSeconds) { Scheduler.Tick(Lounge, new TickContext(sandbox, TimeSpan.FromMilliseconds(16), TimeSpan.FromSeconds(gameSeconds))); } public string[] Log() { return Lounge.Log.ToArray(); } } /// /// Saves and as one scene, so they share the latches, and /// loads it back. /// public static LoungeScene Reload(Lounge lounge, ContentType content) { SaveSession session = ArcConverterTests.Session(); var scene = new LoungeScene { Lounge = lounge, Content = content }; return (LoungeScene)session.FromNode( session.ToNode(scene, typeof(LoungeScene)), typeof(LoungeScene)); } /// /// Adds the script of to a scheduler of its own over the lounge that was loaded. /// public static Room Resumed(LoungeScene loaded) where ContentType : Arc { var returnMe = new Room(loaded.Lounge); returnMe.Scheduler.Add(loaded.Content); return returnMe; } public class ReloadTests : TestFixture { public void WaitReloadedMidWait_ResumesWhenTheLoadedLatchIsSet() { var original = new Room(); var script = new LoungeDoorScript(); original.Scheduler.Add(script); original.TickAt(0); Room room = Resumed(Reload(original.Lounge, script)); room.Lounge.Door.Set(); room.TickAt(0.1); CheckEqual(new[] { "start", "door" }, room.Log()); } public void WaitReloadedMidWait_StillWaitsUntilTheLoadedLatchIsSet() { var original = new Room(); var script = new LoungeDoorScript(); original.Scheduler.Add(script); original.TickAt(0); Room room = Resumed(Reload(original.Lounge, script)); room.TickAt(0.1); room.TickAt(0.2); CheckEqual(new[] { "start" }, room.Log()); CheckEqual(1, room.Scheduler.SuspendedCount); } public void WaitReloadedAfterTheLatchWasSetBeforeTheArcRan_Resumes() { var original = new Room(); var script = new LoungeDoorScript(); original.Scheduler.Add(script); original.TickAt(0); original.Lounge.Door.Set(); Room room = Resumed(Reload(original.Lounge, script)); room.TickAt(0.1); CheckEqual(new[] { "start", "door" }, room.Log()); } public void WaitReloadedSatisfied_WaitsAgainWhenTheLoadedLatchIsClearedBeforeTheArcRuns() { var original = new Room(); var script = new LoungeDoorScript(); original.Scheduler.Add(script); original.TickAt(0); original.Lounge.Door.Set(); Room room = Resumed(Reload(original.Lounge, script)); room.Lounge.Door.Clear(); room.TickAt(0.1); CheckEqual(new[] { "start" }, room.Log()); room.Lounge.Door.Set(); room.TickAt(0.2); CheckEqual(new[] { "start", "door" }, room.Log()); } public void WaitForClearReloadedMidWait_ResumesWhenTheLoadedLatchIsCleared() { var original = new Room(); original.Lounge.Door.Set(); var script = new LoungeClearScript(); original.Scheduler.Add(script); original.TickAt(0); Room room = Resumed(Reload(original.Lounge, script)); room.TickAt(0.1); CheckEqual(new[] { "start" }, room.Log()); room.Lounge.Door.Clear(); room.TickAt(0.2); CheckEqual(new[] { "start", "clear" }, room.Log()); } public void WaitReloadedAfterItWasPassed_LeavesTheLoadedLatchWithoutSubscriptions() { var original = new Room(); var script = new LoungeThenSleepScript(); original.Scheduler.Add(script); original.TickAt(0); original.Lounge.Door.Set(); original.TickAt(0.1); Room room = Resumed(Reload(original.Lounge, script)); CheckEqual(0, room.Lounge.Door.SubscriptionCount); CheckEqual(0, room.Lounge.Door.Inverse.SubscriptionCount); } public void WaitReloadedAfterItWasPassed_IsLeftAloneWhenTheLoadedLatchChanges() { var original = new Room(); var script = new LoungeThenSleepScript(); original.Scheduler.Add(script); original.TickAt(0); original.Lounge.Door.Set(); original.TickAt(0.1); Room room = Resumed(Reload(original.Lounge, script)); room.TickAt(0.2); room.Lounge.Door.Clear(); room.Lounge.Door.Set(); CheckEqual(1, room.Scheduler.SleepingCount); } } public class ListTests : TestFixture { public void WaitAllReloadedWithOneLatchSet_ResumesWhenTheLoadedOtherIsSet() { var original = new Room(); var script = new LoungeBothScript(); original.Scheduler.Add(script); original.TickAt(0); original.Lounge.Door.Set(); original.TickAt(0.1); Room room = Resumed(Reload(original.Lounge, script)); room.TickAt(0.2); CheckEqual(new[] { "start" }, room.Log()); room.Lounge.Alarm.Set(); room.TickAt(0.3); CheckEqual(new[] { "start", "both" }, room.Log()); } public void WaitAllReloadedWithOneLatchSet_WaitsAgainWhenTheLoadedOneIsClearedAndSetOnlyLater() { var original = new Room(); var script = new LoungeBothScript(); original.Scheduler.Add(script); original.TickAt(0); original.Lounge.Door.Set(); Room room = Resumed(Reload(original.Lounge, script)); room.Lounge.Door.Clear(); room.Lounge.Alarm.Set(); room.TickAt(0.1); CheckEqual(new[] { "start" }, room.Log()); room.Lounge.Door.Set(); room.TickAt(0.2); CheckEqual(new[] { "start", "both" }, room.Log()); } public void WaitAnyReloadedMidWait_ResumesWhenEitherLoadedLatchIsSet() { var original = new Room(); var script = new LoungeEitherScript(); original.Scheduler.Add(script); original.TickAt(0); Room room = Resumed(Reload(original.Lounge, script)); room.Lounge.Alarm.Set(); room.TickAt(0.1); CheckEqual(new[] { "start", "alarm" }, room.Log()); } public void WaitAnyReloaded_SubscribesTheArcToBothLoadedLatches() { var original = new Room(); var script = new LoungeEitherScript(); original.Scheduler.Add(script); original.TickAt(0); Room room = Resumed(Reload(original.Lounge, script)); CheckEqual(1, room.Lounge.Door.SubscriptionCount); CheckEqual(1, room.Lounge.Alarm.SubscriptionCount); } } public class TimeoutTests : TestFixture { public void WaitReloadedMidWait_ResumesWhenTheLoadedLatchIsSetInTime() { var original = new Room(); var script = new LoungeTimedScript(); original.Scheduler.Add(script); original.TickAt(0); Room room = Resumed(Reload(original.Lounge, script)); room.Lounge.Alarm.Set(); room.TickAt(1); CheckEqual(new[] { "start", "alarm" }, room.Log()); } public void WaitReloadedMidWait_StillTimesOutAtTheSavedDeadline() { var original = new Room(); var script = new LoungeTimedScript(); original.Scheduler.Add(script); original.TickAt(0); Room room = Resumed(Reload(original.Lounge, script)); room.TickAt(1.9); CheckEqual(new[] { "start" }, room.Log()); room.TickAt(2); CheckEqual(new[] { "start", "timed out" }, room.Log()); } public void WaitReloadedAfterItTimedOut_IsSubscribedToNothing() { var original = new Room(); var script = new LoungeTimedScript(); original.Scheduler.Add(script); original.TickAt(0); original.TickAt(2); Room room = Resumed(Reload(original.Lounge, script)); CheckEqual(0, room.Lounge.Alarm.SubscriptionCount); } } } }