using System.IO;
using UnitTestSharp;
using Vellum;
namespace Ariadne.Vellum.UnitTests
{
public class TriggerWaitConverterTests : TestFixture
{
public class FromNodeTests : TestFixture
{
[IgnoreTest]
public TriggerWait Reload(TriggerWait wait)
{
SaveSession session = ArcConverterTests.Session();
return (TriggerWait)session.FromNode(session.ToNode(wait, typeof(TriggerWait)), typeof(TriggerWait));
}
[IgnoreTest]
public SaveNode Saved(TriggerWait wait, SaveSession session)
{
return session.ToNode(wait, typeof(TriggerWait)).Resolved;
}
public void WaitInProgress_LoadsWithItsProgress()
{
var door = new Trigger();
TriggerWait wait = TriggerConverterTests.WaitOn(capacity: 3, requiresAll: true, door, new Trigger());
door.Raise();
TriggerWait loaded = Reload(wait);
CheckEqual(3, loaded.Triggers.Length);
CheckEqual(2, loaded.Count);
CheckEqual(wait.Wait, loaded.Wait);
CheckTrue(loaded.RequiresAll);
CheckEqual(1, loaded.Seen);
CheckEqual(-1, loaded.Fired);
CheckFalse(loaded.Complete);
}
public void WaitThatIsOver_LoadsWithTheTriggerThatEndedIt()
{
var door = new Trigger();
TriggerWait wait = TriggerConverterTests.WaitOn(capacity: 2, requiresAll: false, new Trigger(), door);
door.Raise();
TriggerWait loaded = Reload(wait);
CheckTrue(loaded.Complete);
CheckEqual(1, loaded.Fired);
CheckTrue(ReferenceEquals(loaded.Triggers[1], loaded.Result));
}
public void WaitThatNeverBegan_LoadsEmpty()
{
TriggerWait loaded = Reload(new TriggerWait(capacity: 4));
CheckEqual(4, loaded.Triggers.Length);
CheckEqual(0, loaded.Count);
CheckEqual(0, loaded.Wait);
CheckFalse(loaded.Complete);
}
public void WaitThatExpired_LoadsOverWithNothingWaitedOn()
{
TriggerWait wait = TriggerConverterTests.WaitOn(capacity: 2, requiresAll: false, new Trigger(),
new Trigger());
wait.Expire();
TriggerWait loaded = Reload(wait);
CheckEqual(2, loaded.Triggers.Length);
CheckEqual(0, loaded.Count);
CheckEqual(wait.Wait, loaded.Wait);
CheckTrue(loaded.Complete);
CheckNull(loaded.Result);
}
public void WaitOfTheMostTriggers_Loads()
{
TriggerWait loaded = Reload(new TriggerWait(TriggerWait.MaximumTriggers));
CheckEqual(TriggerWait.MaximumTriggers, loaded.Triggers.Length);
}
public void WaitOfTheMostTriggersAllRaised_LoadsComplete()
{
var triggers = new Trigger[TriggerWait.MaximumTriggers];
for (int i = 0; i < triggers.Length; ++i)
{
triggers[i] = new Trigger();
}
TriggerWait wait = TriggerConverterTests.WaitOn(TriggerWait.MaximumTriggers, requiresAll: true,
triggers);
foreach (Trigger trigger in triggers)
{
trigger.Raise();
}
TriggerWait loaded = Reload(wait);
CheckTrue(loaded.Complete);
CheckEqual(TriggerWait.MaximumTriggers - 1, loaded.Fired);
}
public void LoadedTriggers_AreSubscribedToTheLoadedWait()
{
var door = new Trigger();
TriggerWait wait = TriggerConverterTests.WaitOn(capacity: 1, requiresAll: false, door);
TriggerWait loaded = Reload(wait);
CheckEqual(1, loaded.Triggers[0].SubscriptionCount);
CheckTrue(ReferenceEquals(loaded.Subscriptions[0], loaded.Triggers[0].SubscriptionAt(0)));
}
public void NodeWithNoTriggers_Throws()
{
SaveSession session = ArcConverterTests.Session();
SaveNode node = Saved(new TriggerWait(capacity: 1), session);
node.Entries.Remove("triggers");
CheckThrow(typeof(InvalidDataException));
session.FromNode(node, typeof(TriggerWait));
}
public void CapacityOfZero_Throws()
{
SaveSession session = ArcConverterTests.Session();
SaveNode node = Saved(new TriggerWait(capacity: 1), session);
node.Entries["capacity"] = session.ToNode(0);
CheckThrow(typeof(InvalidDataException));
session.FromNode(node, typeof(TriggerWait));
}
public void CapacityPastTheMaximum_Throws()
{
SaveSession session = ArcConverterTests.Session();
SaveNode node = Saved(new TriggerWait(capacity: 1), session);
node.Entries["capacity"] = session.ToNode(TriggerWait.MaximumTriggers + 1);
CheckThrow(typeof(InvalidDataException));
session.FromNode(node, typeof(TriggerWait));
}
public void MoreTriggersThanTheCapacity_Throws()
{
SaveSession session = ArcConverterTests.Session();
TriggerWait wait = TriggerConverterTests.WaitOn(capacity: 2, requiresAll: false, new Trigger(),
new Trigger());
SaveNode node = Saved(wait, session);
node.Entries["capacity"] = session.ToNode(1);
CheckThrow(typeof(InvalidDataException));
session.FromNode(node, typeof(TriggerWait));
}
public void TriggerThatEndedItPastTheOnesListed_Throws()
{
SaveSession session = ArcConverterTests.Session();
var door = new Trigger();
SaveNode node = Saved(TriggerConverterTests.WaitOn(capacity: 1, requiresAll: false, door), session);
node.Entries["fired"] = session.ToNode(1);
CheckThrow(typeof(InvalidDataException));
session.FromNode(node, typeof(TriggerWait));
}
public void TriggerThatEndedItBelowNone_Throws()
{
SaveSession session = ArcConverterTests.Session();
SaveNode node = Saved(new TriggerWait(capacity: 1), session);
node.Entries["fired"] = session.ToNode(-2);
CheckThrow(typeof(InvalidDataException));
session.FromNode(node, typeof(TriggerWait));
}
public void RaisedBitsPastTheTriggersListed_Throw()
{
SaveSession session = ArcConverterTests.Session();
TriggerWait wait = TriggerConverterTests.WaitOn(capacity: 2, requiresAll: true, new Trigger(),
new Trigger());
SaveNode node = Saved(wait, session);
node.Entries["seen"] = session.ToNode(4);
CheckThrow(typeof(InvalidDataException));
session.FromNode(node, typeof(TriggerWait));
}
public void WaitThatIsOverButSaysNoTriggerEndedIt_Throws()
{
SaveSession session = ArcConverterTests.Session();
SaveNode node = Saved(
TriggerConverterTests.WaitOn(capacity: 1, requiresAll: false, new Trigger()), session);
node.Entries["seen"] = session.ToNode(1);
CheckThrow(typeof(InvalidDataException));
session.FromNode(node, typeof(TriggerWait));
}
public void WaitThatGoesOnButSaysATriggerEndedIt_Throws()
{
SaveSession session = ArcConverterTests.Session();
SaveNode node = Saved(
TriggerConverterTests.WaitOn(capacity: 1, requiresAll: false, new Trigger()), session);
node.Entries["fired"] = session.ToNode(0);
CheckThrow(typeof(InvalidDataException));
session.FromNode(node, typeof(TriggerWait));
}
}
///
/// A condition no wait could be paused in, since only latches and their inverses are saved.
///
public class OddCondition : Condition
{
public override bool IsSet => true;
}
///
/// A slot that counts the times it is woken.
///
public class CountingSlot : WakeSlot
{
public int Wakes;
public override void Wake()
{
++Wakes;
}
}
public class FromNodeOnConditionsTests : TestFixture
{
[IgnoreTest]
public TriggerWait Reload(TriggerWait wait)
{
SaveSession session = ArcConverterTests.Session();
return (TriggerWait)session.FromNode(session.ToNode(wait, typeof(TriggerWait)), typeof(TriggerWait));
}
[IgnoreTest]
public SaveNode Saved(TriggerWait wait, SaveSession session)
{
return session.ToNode(wait, typeof(TriggerWait)).Resolved;
}
public void WaitInProgress_LoadsOnConditionsWithItsProgress()
{
TriggerWait wait = LatchConverterTests.WaitOn(capacity: 3, requiresAll: true,
new Latch(initiallySet: true), new Latch());
TriggerWait loaded = Reload(wait);
CheckTrue(loaded.OnConditions);
CheckEqual(3, loaded.Conditions.Length);
CheckEqual(0, loaded.Triggers.Length);
CheckEqual(3, loaded.Subscriptions.Length);
CheckEqual(2, loaded.Count);
CheckEqual(wait.Wait, loaded.Wait);
CheckTrue(loaded.RequiresAll);
CheckTrue(loaded.Conditions[0].IsSet);
CheckFalse(loaded.Conditions[1].IsSet);
CheckFalse(loaded.Complete);
}
public void WaitOnAnInverse_LoadsTheInverseOfTheLoadedLatch()
{
var door = new Latch(initiallySet: true);
TriggerWait wait = LatchConverterTests.WaitOn(capacity: 1, requiresAll: false, door.Inverse);
TriggerWait loaded = Reload(wait);
var inverse = (InvertedLatch)loaded.Conditions[0];
CheckTrue(inverse.Original.IsSet);
CheckTrue(ReferenceEquals(inverse.Original.Inverse, inverse));
CheckFalse(loaded.Complete);
}
public void WaitOnALatchAndItsInverse_LoadsOneLatch()
{
var door = new Latch();
TriggerWait wait = LatchConverterTests.WaitOn(capacity: 2, requiresAll: false, door, door.Inverse);
TriggerWait loaded = Reload(wait);
var latch = (Latch)loaded.Conditions[0];
CheckTrue(ReferenceEquals(latch.Inverse, loaded.Conditions[1]));
}
public void WaitThatIsSatisfiedButNotFinished_LoadsOverWithTheConditionThatAnswersIt()
{
var door = new Latch(initiallySet: true);
TriggerWait wait = LatchConverterTests.WaitOn(capacity: 2, requiresAll: false, new Latch(), door);
TriggerWait loaded = Reload(wait);
CheckTrue(loaded.Complete);
CheckTrue(ReferenceEquals(loaded.Conditions[1], loaded.ConditionResult));
}
public void WaitThatWasFinished_LoadsOverWithNothingWaitedOn()
{
TriggerWait wait = LatchConverterTests.WaitOn(capacity: 2, requiresAll: false, new Latch(),
new Latch());
wait.Finish();
TriggerWait loaded = Reload(wait);
CheckTrue(loaded.OnConditions);
CheckEqual(0, loaded.Count);
CheckEqual(wait.Wait, loaded.Wait);
CheckTrue(loaded.Complete);
CheckNull(loaded.ConditionResult);
}
public void WaitThatNeverBegan_LoadsEmptyOnConditions()
{
TriggerWait loaded = Reload(new TriggerWait(capacity: 4, onConditions: true));
CheckEqual(4, loaded.Conditions.Length);
CheckEqual(0, loaded.Count);
CheckFalse(loaded.Complete);
}
public void LoadedConditions_AreSubscribedToTheLoadedWait()
{
TriggerWait wait = LatchConverterTests.WaitOn(capacity: 1, requiresAll: false, new Latch());
TriggerWait loaded = Reload(wait);
CheckEqual(1, loaded.Conditions[0].SubscriptionCount);
CheckTrue(ReferenceEquals(loaded.Subscriptions[0], loaded.Conditions[0].SubscriptionAt(0)));
}
public void LoadedWait_WakesItsArcWhenItsLatchIsSet()
{
var door = new Latch();
TriggerWait wait = LatchConverterTests.WaitOn(capacity: 1, requiresAll: false, door);
TriggerWait loaded = Reload(wait);
var slot = new CountingSlot();
loaded.Attach(slot);
((Latch)loaded.Conditions[0]).Set();
CheckEqual(1, slot.Wakes);
}
public void ConditionThatIsNotALatch_CannotBeSaved()
{
SaveSession session = ArcConverterTests.Session();
TriggerWait wait = LatchConverterTests.WaitOn(capacity: 1, requiresAll: false, new OddCondition());
CheckThrow(typeof(System.InvalidOperationException));
session.ToNode(wait, typeof(TriggerWait));
}
public void MoreConditionsThanTheCapacity_Throws()
{
SaveSession session = ArcConverterTests.Session();
TriggerWait wait = LatchConverterTests.WaitOn(capacity: 2, requiresAll: false, new Latch(),
new Latch());
SaveNode node = Saved(wait, session);
node.Entries["capacity"] = session.ToNode(1);
CheckThrow(typeof(InvalidDataException));
session.FromNode(node, typeof(TriggerWait));
}
public void ConditionsThatAreNotAList_Throw()
{
SaveSession session = ArcConverterTests.Session();
SaveNode node = Saved(new TriggerWait(capacity: 1, onConditions: true), session);
node.Entries["conditions"] = session.ToNode(5);
CheckThrow(typeof(InvalidDataException));
session.FromNode(node, typeof(TriggerWait));
}
public void ConditionWithNoLatch_Throws()
{
SaveSession session = ArcConverterTests.Session();
TriggerWait wait = LatchConverterTests.WaitOn(capacity: 1, requiresAll: false, new Latch());
SaveNode node = Saved(wait, session);
node.Entries["conditions"].Items[0].Entries.Remove("latch");
CheckThrow(typeof(InvalidDataException));
session.FromNode(node, typeof(TriggerWait));
}
public void ConditionWithNoInvertedFlag_Throws()
{
SaveSession session = ArcConverterTests.Session();
TriggerWait wait = LatchConverterTests.WaitOn(capacity: 1, requiresAll: false, new Latch());
SaveNode node = Saved(wait, session);
node.Entries["conditions"].Items[0].Entries.Remove("inverted");
CheckThrow(typeof(InvalidDataException));
session.FromNode(node, typeof(TriggerWait));
}
}
}
}