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);
}
}
}
}