using System; using System.Collections.Generic; using UnitTestSharp; namespace Ariadne.UnitTests { public class TriggerWaitTests : TestFixture { public class CtorTests : TestFixture { public void CapacityOfZero_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); new TriggerWait(capacity: 0); } public void CapacityPastTheMaximum_Throws() { CheckThrow(typeof(ArgumentOutOfRangeException)); new TriggerWait(TriggerWait.MaximumTriggers + 1); } public void CapacityOfOneAndOfTheMaximum_AreAllowed() { CheckEqual(1, new TriggerWait(capacity: 1).Triggers.Length); CheckEqual(TriggerWait.MaximumTriggers, new TriggerWait(TriggerWait.MaximumTriggers).Triggers.Length); } public void OnConditions_HoldsConditionsAndNoTriggers() { var wait = new TriggerWait(capacity: 3, onConditions: true); CheckTrue(wait.OnConditions); CheckEqual(3, wait.Conditions.Length); CheckEqual(0, wait.Triggers.Length); CheckEqual(3, wait.Subscriptions.Length); } public void ByDefault_HoldsTriggersAndNoConditions() { var wait = new TriggerWait(capacity: 3); CheckFalse(wait.OnConditions); CheckEqual(0, wait.Conditions.Length); } public void MakesASubscriptionForEachPosition() { var wait = new TriggerWait(capacity: 3); CheckEqual(3, wait.Subscriptions.Length); for (int i = 0; i < 3; ++i) { CheckTrue(ReferenceEquals(wait, wait.Subscriptions[i].Target)); CheckEqual(i, wait.Subscriptions[i].Index); } } public void StartsWithNothingWaitedOnOrFired() { var wait = new TriggerWait(capacity: 2); CheckEqual(0, wait.Count); CheckEqual(0, wait.Wait); CheckEqual(0, wait.Seen); CheckEqual(-1, wait.Fired); CheckNull(wait.Slot); CheckNull(wait.Result); } } public class BeginTests : TestFixture { private List woken; private Frame frame; public override void TestSetup() { woken = new List(); frame = new Frame { Wake = new RecordingSlot(woken, order: 0) }; } public void TakesTheFramesSlot() { var wait = new TriggerWait(capacity: 2); wait.Begin(frame, requiresAll: false); CheckTrue(ReferenceEquals(frame.Wake, wait.Slot)); } public void FrameWithoutASlot_Throws() { CheckThrow(typeof(InvalidOperationException)); new TriggerWait(capacity: 2).Begin(new Frame(), requiresAll: false); } public void NullFrame_Throws() { CheckThrow(typeof(ArgumentNullException)); new TriggerWait(capacity: 2).Begin(null, requiresAll: false); } public void RecordsWhetherEveryTriggerIsRequired() { var wait = new TriggerWait(capacity: 2); wait.Begin(frame, requiresAll: true); CheckTrue(wait.RequiresAll); wait.Begin(frame, requiresAll: false); CheckFalse(wait.RequiresAll); } public void EachWait_HasANewNumber() { var wait = new TriggerWait(capacity: 2); wait.Begin(frame, requiresAll: false); CheckEqual(1, wait.Wait); wait.Begin(frame, requiresAll: false); CheckEqual(2, wait.Wait); } public void ClearsWhatTheEarlierWaitRecorded() { var wait = new TriggerWait(capacity: 2); var trigger = new Trigger(); wait.Begin(frame, requiresAll: false); wait.Add(trigger); trigger.Raise(); CheckEqual(0, wait.Fired); wait.Begin(frame, requiresAll: false); CheckEqual(0, wait.Count); CheckEqual(0, wait.Seen); CheckEqual(-1, wait.Fired); CheckNull(wait.Result); } } public class AddTests : TestFixture { private List woken; private TriggerWait wait; public override void TestSetup() { woken = new List(); wait = new TriggerWait(capacity: 2); wait.Begin(new Frame { Wake = new RecordingSlot(woken, order: 0) }, requiresAll: false); } public void StoresTheTriggerAndSubscribesToIt() { var trigger = new Trigger(); wait.Add(trigger); CheckEqual(1, wait.Count); CheckTrue(ReferenceEquals(trigger, wait.Triggers[0])); CheckEqual(1, trigger.SubscriptionCount); } public void TriggersKeepTheirPositions() { var first = new Trigger(); var second = new Trigger(); wait.Add(first); wait.Add(second); CheckTrue(ReferenceEquals(first, wait.Triggers[0])); CheckTrue(ReferenceEquals(second, wait.Triggers[1])); } public void MoreTriggersThanTheWaitHolds_Throws() { wait.Add(new Trigger()); wait.Add(new Trigger()); CheckThrow(typeof(InvalidOperationException)); wait.Add(new Trigger()); } public void NullTrigger_Throws() { CheckThrow(typeof(ArgumentNullException)); wait.Add((Trigger)null); } public void ConditionOnAWaitOnTriggers_Throws() { CheckThrow(typeof(InvalidOperationException)); wait.Add(new Latch()); } public void TriggerOnAWaitOnConditions_Throws() { var onConditions = new TriggerWait(capacity: 1, onConditions: true); CheckThrow(typeof(InvalidOperationException)); onConditions.Add(new Trigger()); } public void StoresTheConditionAndSubscribesToIt() { var onConditions = new TriggerWait(capacity: 2, onConditions: true); onConditions.Begin(new Frame { Wake = new RecordingSlot(woken, order: 0) }, requiresAll: false); var latch = new Latch(); onConditions.Add(latch); CheckEqual(1, onConditions.Count); CheckTrue(ReferenceEquals(latch, onConditions.Conditions[0])); CheckEqual(1, latch.SubscriptionCount); } public void MoreConditionsThanTheWaitHolds_Throws() { var onConditions = new TriggerWait(capacity: 1, onConditions: true); onConditions.Begin(new Frame { Wake = new RecordingSlot(woken, order: 0) }, requiresAll: false); onConditions.Add(new Latch()); CheckThrow(typeof(InvalidOperationException)); onConditions.Add(new Latch()); } [IgnoreTest] public TriggerWait Begun(bool requiresAll, int capacity) { var returnMe = new TriggerWait(capacity, onConditions: true); returnMe.Begin(new Frame { Wake = new RecordingSlot(woken, order: 0) }, requiresAll); return returnMe; } public void WaitForEveryWithALatchAndItsInverse_Throws() { var latch = new Latch(); TriggerWait onConditions = Begun(requiresAll: true, capacity: 2); onConditions.Add(latch); CheckThrow(typeof(InvalidOperationException)); onConditions.Add(latch.Inverse); } public void WaitForEveryWithAnInverseAndItsLatch_Throws() { var latch = new Latch(); TriggerWait onConditions = Begun(requiresAll: true, capacity: 2); onConditions.Add(latch.Inverse); CheckThrow(typeof(InvalidOperationException)); onConditions.Add(latch); } public void WaitForAnyWithALatchAndItsInverse_IsAllowed() { var latch = new Latch(); TriggerWait onConditions = Begun(requiresAll: false, capacity: 2); onConditions.Add(latch); onConditions.Add(latch.Inverse); CheckEqual(2, onConditions.Count); } public void WaitForEveryWithUnrelatedLatches_IsAllowed() { var latch = new Latch(); TriggerWait onConditions = Begun(requiresAll: true, capacity: 3); onConditions.Add(latch); onConditions.Add(new Latch().Inverse); onConditions.Add(latch); CheckEqual(3, onConditions.Count); } public void NullCondition_Throws() { var onConditions = new TriggerWait(capacity: 1, onConditions: true); CheckThrow(typeof(ArgumentNullException)); onConditions.Add((Condition)null); } } public class HoldsTests : TestFixture { private List woken; public override void TestSetup() { woken = new List(); } public void Trigger_IsHeldAtItsPositionOnly() { var first = new Trigger(); var second = new Trigger(); TriggerWait wait = TriggerTests.WaitOf(woken, order: 0, first, second); CheckTrue(wait.Holds(first, 0)); CheckTrue(wait.Holds(second, 1)); CheckFalse(wait.Holds(first, 1)); CheckFalse(wait.Holds(new Trigger(), 0)); } public void Condition_IsHeldAtItsPositionOnly() { var first = new Latch(); var second = new Latch(); TriggerWait wait = LatchTests.WaitOn(woken, order: 0, first, second.Inverse); CheckTrue(wait.Holds(first, 0)); CheckTrue(wait.Holds(second.Inverse, 1)); CheckFalse(wait.Holds(second, 1)); CheckFalse(wait.Holds(first, 1)); } public void PositionOutsideTheWait_IsNotHeld() { var trigger = new Trigger(); TriggerWait wait = TriggerTests.WaitOf(woken, order: 0, trigger); CheckFalse(wait.Holds(trigger, -1)); CheckFalse(wait.Holds(trigger, 1)); } } public class ConditionResultTests : TestFixture { private List woken; private Latch first; private Latch second; public override void TestSetup() { woken = new List(); first = new Latch(); second = new Latch(); } public void WaitOnTriggers_IsNull() { CheckNull(TriggerTests.WaitOf(woken, order: 0, new Trigger()).ConditionResult); } public void WaitThatGoesOn_IsNull() { CheckNull(LatchTests.WaitOn(woken, order: 0, first, second).ConditionResult); } public void WaitForAny_IsTheFirstThatIsSetInTheOrderTheyWereAdded() { second.Set(); TriggerWait wait = LatchTests.WaitOn(woken, order: 0, first, second); CheckTrue(ReferenceEquals(second, wait.ConditionResult)); first.Set(); CheckTrue(ReferenceEquals(first, wait.ConditionResult)); } public void WaitForEvery_IsTheLastAdded() { first.Set(); second.Set(); TriggerWait wait = LatchTests.WaitOn(woken, order: 0, tag: 0, requiresAll: true, first, second); CheckTrue(ReferenceEquals(second, wait.ConditionResult)); } public void WaitForEveryOneOfWhichIsClear_IsNull() { first.Set(); TriggerWait wait = LatchTests.WaitOn(woken, order: 0, tag: 0, requiresAll: true, first, second); CheckNull(wait.ConditionResult); } public void WaitForEveryOfNone_IsNull() { var wait = new TriggerWait(capacity: 1, onConditions: true); wait.Begin(new Frame { Wake = new RecordingSlot(woken, order: 0) }, requiresAll: true); CheckNull(wait.ConditionResult); } } public class FinishTests : TestFixture { private List woken; private Latch door; public override void TestSetup() { woken = new List(); door = new Latch(initiallySet: true); } public void WaitOnTriggers_Throws() { CheckThrow(typeof(InvalidOperationException)); TriggerTests.WaitOf(woken, order: 0, new Trigger()).Finish(); } public void ReturnsTheConditionThatAnsweredTheWait() { TriggerWait wait = LatchTests.WaitOn(woken, order: 0, new Latch(), door); CheckTrue(ReferenceEquals(door, wait.Finish())); } public void WaitThatGoesOn_ReturnsNull() { CheckNull(LatchTests.WaitOn(woken, order: 0, new Latch()).Finish()); } public void EmptiesTheWaitAndEndsIt() { TriggerWait wait = LatchTests.WaitOn(woken, order: 0, door); wait.Finish(); CheckTrue(wait.Complete); CheckEqual(0, wait.Count); CheckNull(wait.ConditionResult); } public void ConditionsThatChangeAfterwards_WakeNothing() { var latch = new Latch(); LatchTests.WaitOn(woken, order: 0, latch).Finish(); latch.Set(); CheckEqual(0, woken.Count); } } public class NotifyTests : TestFixture { private List woken; private Latch door; public override void TestSetup() { woken = new List(); door = new Latch(); } public void WaitOnTriggers_Throws() { CheckThrow(typeof(InvalidOperationException)); TriggerTests.WaitOf(woken, order: 0, new Trigger()).Notify(); } public void WaitThatIsOver_WakesTheArc() { TriggerWait wait = LatchTests.WaitOn(woken, order: 5, door); door.Set(); woken.Clear(); wait.Notify(); CheckEqual(new[] { 5 }, woken.ToArray()); } public void WaitThatGoesOn_WakesNothing() { LatchTests.WaitOn(woken, order: 0, door).Notify(); CheckEqual(0, woken.Count); } public void WaitThatIsOverWithNoSlot_Throws() { TriggerWait wait = LatchTests.WaitOn(woken, order: 0, new Latch(initiallySet: true)); wait.Slot = null; CheckThrow(typeof(InvalidOperationException)); wait.Notify(); } } public class CompleteTests : TestFixture { private List woken; private Frame frame; public override void TestSetup() { woken = new List(); frame = new Frame { Wake = new RecordingSlot(woken, order: 0) }; } [IgnoreTest] public TriggerWait Waiting(bool requiresAll, int triggers) { var returnMe = new TriggerWait(capacity: Math.Max(1, triggers)); returnMe.Begin(frame, requiresAll); for (int i = 0; i < triggers; ++i) { returnMe.Add(new Trigger()); } return returnMe; } public void NothingRaised_IsNotComplete() { CheckFalse(Waiting(requiresAll: false, triggers: 2).Complete); CheckFalse(Waiting(requiresAll: true, triggers: 2).Complete); } public void AnyOfSeveral_IsCompleteWhenOneIsRaised() { TriggerWait wait = Waiting(requiresAll: false, triggers: 3); wait.Mark(1); CheckTrue(wait.Complete); } public void AllOfSeveral_IsNotCompleteUntilEveryOneIsRaised() { TriggerWait wait = Waiting(requiresAll: true, triggers: 3); wait.Mark(0); wait.Mark(2); CheckFalse(wait.Complete); wait.Mark(1); CheckTrue(wait.Complete); } public void AllOfNone_IsComplete() { CheckTrue(Waiting(requiresAll: true, triggers: 0).Complete); } public void AnyOfNone_IsNotComplete() { CheckFalse(Waiting(requiresAll: false, triggers: 0).Complete); } public void AllOfTheMaximum_NeedsEveryBit() { TriggerWait wait = Waiting(requiresAll: true, triggers: TriggerWait.MaximumTriggers); for (int i = 0; i < TriggerWait.MaximumTriggers - 1; ++i) { wait.Mark(i); } CheckFalse(wait.Complete); wait.Mark(TriggerWait.MaximumTriggers - 1); CheckTrue(wait.Complete); } public void ConditionsNoneOfWhichAreSet_IsNotComplete() { var first = new Latch(); var second = new Latch(); CheckFalse(LatchTests.WaitOn(woken, order: 0, first, second).Complete); CheckFalse(LatchTests.WaitOn(woken, order: 0, tag: 0, requiresAll: true, first, second).Complete); } public void ConditionsAnyOfWhichIsSet_CompleteAWaitForAny() { var set = new Latch(initiallySet: true); CheckTrue(LatchTests.WaitOn(woken, order: 0, new Latch(), set).Complete); } public void ConditionsNotAllOfWhichAreSet_DoNotCompleteAWaitForEvery() { var set = new Latch(initiallySet: true); CheckFalse(LatchTests.WaitOn(woken, order: 0, tag: 0, requiresAll: true, set, new Latch()).Complete); } public void ConditionsAllOfWhichAreSet_CompleteAWaitForEvery() { var first = new Latch(initiallySet: true); var second = new Latch(initiallySet: true); CheckTrue(LatchTests.WaitOn(woken, order: 0, tag: 0, requiresAll: true, first, second).Complete); } public void ConditionThatIsClearedAgain_UnCompletesTheWait() { var latch = new Latch(); TriggerWait wait = LatchTests.WaitOn(woken, order: 0, latch); latch.Set(); latch.Clear(); CheckFalse(wait.Complete); } public void WaitForEveryOfNoConditions_IsCompleteAndForAnyIsNot() { var every = new TriggerWait(capacity: 1, onConditions: true); every.Begin(frame, requiresAll: true); var any = new TriggerWait(capacity: 1, onConditions: true); any.Begin(frame, requiresAll: false); CheckTrue(every.Complete); CheckFalse(any.Complete); } } public class AttachTests : TestFixture { private List woken; private Trigger door; private Trigger alarm; public override void TestSetup() { woken = new List(); door = new Trigger(); alarm = new Trigger(); } public void NullSlot_Throws() { CheckThrow(typeof(ArgumentNullException)); new TriggerWait(capacity: 1).Attach(null); } public void SetsTheSlot() { var wait = new TriggerWait(capacity: 1); var slot = new WakeSlot(); wait.Attach(slot); CheckTrue(ReferenceEquals(slot, wait.Slot)); } public void WaitThatHasNotBegun_SubscribesNothing() { new TriggerWait(capacity: 1).Attach(new WakeSlot()); CheckEqual(0, door.SubscriptionCount); } public void WaitInProgress_SubscribesEveryTriggerItIsMissingFrom() { var wait = new TriggerWait(capacity: 2); wait.Begin(new Frame { Wake = new RecordingSlot(woken, order: 0) }, requiresAll: false); wait.Triggers[0] = door; wait.Triggers[1] = alarm; wait.Count = 2; wait.Attach(new RecordingSlot(woken, order: 1)); CheckEqual(1, door.SubscriptionCount); CheckEqual(1, alarm.SubscriptionCount); } public void WaitThatTriggersAlreadyHold_IsNotSubscribedAgain() { TriggerWait wait = TriggerTests.WaitOf(woken, order: 0, door, alarm); wait.Attach(new RecordingSlot(woken, order: 1)); CheckEqual(1, door.SubscriptionCount); CheckEqual(1, alarm.SubscriptionCount); } public void WaitWhoseSubscriptionsWereSwept_IsSubscribedAgain() { TriggerWait wait = TriggerTests.WaitOf(woken, order: 0, door); wait.Slot.Dropped = true; for (int i = 0; i < 20; ++i) { TriggerTests.WaitOf(woken, order: 1, door); } var added = new RecordingSlot(woken, order: 2); wait.Attach(added); door.Raise(); CheckTrue(woken.Contains(2)); } public void WaitThatIsOver_SubscribesNothing() { TriggerWait wait = TriggerTests.WaitOf(woken, order: 0, door, alarm); wait.Mark(0); door.Raise(); alarm.Raise(); wait.Attach(new RecordingSlot(woken, order: 1)); CheckEqual(0, alarm.SubscriptionCount); } public void LoadedWaitWhoseSubscriptionWasNotSaved_IsSubscribed() { var wait = new TriggerWait(capacity: 1); wait.Triggers[0] = door; wait.Count = 1; wait.Attach(new RecordingSlot(woken, order: 1)); CheckEqual(1, door.SubscriptionCount); } public void LoadedWaitOnConditionsWhoseSubscriptionWasNotSaved_IsSubscribed() { var latch = new Latch(); var wait = new TriggerWait(capacity: 1, onConditions: true); wait.Conditions[0] = latch; wait.Count = 1; wait.Attach(new RecordingSlot(woken, order: 1)); CheckEqual(1, latch.SubscriptionCount); } public void WaitOnConditionsThatIsOver_SubscribesAnyway() { var latch = new Latch(initiallySet: true); var wait = new TriggerWait(capacity: 1, onConditions: true); wait.Begin(new Frame { Wake = new RecordingSlot(woken, order: 0) }, requiresAll: false); wait.Conditions[0] = latch; wait.Count = 1; wait.Attach(new RecordingSlot(woken, order: 1)); CheckEqual(1, latch.SubscriptionCount); } public void WaitOnConditionsThatConditionsAlreadyHold_IsNotSubscribedAgain() { var latch = new Latch(); TriggerWait wait = LatchTests.WaitOn(woken, order: 0, latch); wait.Attach(new RecordingSlot(woken, order: 1)); CheckEqual(1, latch.SubscriptionCount); } public void WaitOnConditionsWhoseSubscriptionsWereSwept_WakesTheNewSlot() { var latch = new Latch(); TriggerWait wait = LatchTests.WaitOn(woken, order: 0, latch); wait.Slot.Dropped = true; for (int i = 0; i < 20; ++i) { LatchTests.WaitOn(woken, order: 1, latch); } wait.Attach(new RecordingSlot(woken, order: 2)); latch.Set(); CheckTrue(woken.Contains(2)); } } public class ExpireTests : TestFixture { private List woken; private Trigger door; private Trigger alarm; public override void TestSetup() { woken = new List(); door = new Trigger(); alarm = new Trigger(); } public void EmptiesTheWaitAndEndsIt() { TriggerWait wait = TriggerTests.WaitOf(woken, order: 0, door, alarm); wait.Mark(0); wait.Expire(); CheckTrue(wait.Complete); CheckEqual(0, wait.Count); CheckEqual(0, wait.Seen); CheckEqual(-1, wait.Fired); CheckNull(wait.Result); } public void WaitForAllThatWasPartlyRaised_EndsToo() { TriggerWait wait = TriggerTests.WaitOf(woken, order: 0, door, alarm); wait.RequiresAll = true; wait.Mark(0); wait.Expire(); CheckTrue(wait.Complete); } public void LaterRaisesOfItsTriggers_WakeNothing() { TriggerWait wait = TriggerTests.WaitOf(woken, order: 0, door, alarm); wait.Expire(); door.Raise(); alarm.Raise(); CheckEqual(0, woken.Count); } public void LaterRaisesOfItsTriggers_SweepItsSubscriptions() { TriggerWait wait = TriggerTests.WaitOf(woken, order: 0, door, alarm); wait.Expire(); door.Raise(); CheckEqual(0, door.SubscriptionCount); } public void WaitOnConditions_EndsLikeAnyOther() { var latch = new Latch(); TriggerWait wait = LatchTests.WaitOn(woken, order: 0, latch); wait.Expire(); latch.Set(); CheckTrue(wait.Complete); CheckEqual(0, woken.Count); } public void WaitBegunAgain_IsWokenByItsTriggers() { TriggerWait wait = TriggerTests.WaitOf(woken, order: 4, door); wait.Expire(); wait.Begin(new Frame { Wake = new RecordingSlot(woken, order: 4) }, requiresAll: false); wait.Add(door); door.Raise(); CheckEqual(new[] { 4 }, woken.ToArray()); } } public class MarkTests : TestFixture { private List woken; private Frame frame; public override void TestSetup() { woken = new List(); frame = new Frame { Wake = new RecordingSlot(woken, order: 5) }; } [IgnoreTest] public TriggerWait Waiting(bool requiresAll, int triggers) { var returnMe = new TriggerWait(capacity: triggers); returnMe.Begin(frame, requiresAll); for (int i = 0; i < triggers; ++i) { returnMe.Add(new Trigger()); } return returnMe; } public void WaitOnConditions_Throws() { TriggerWait wait = LatchTests.WaitOn(woken, order: 0, new Latch()); CheckThrow(typeof(InvalidOperationException)); wait.Mark(0); } public void IndexBelowZero_Throws() { TriggerWait wait = Waiting(requiresAll: false, triggers: 2); CheckThrow(typeof(ArgumentOutOfRangeException)); wait.Mark(-1); } public void IndexPastTheTriggersAdded_Throws() { TriggerWait wait = Waiting(requiresAll: false, triggers: 2); CheckThrow(typeof(ArgumentOutOfRangeException)); wait.Mark(2); } public void IndexPastTheTriggersAddedButInsideTheCapacity_Throws() { var wait = new TriggerWait(capacity: 4); wait.Begin(frame, requiresAll: false); wait.Add(new Trigger()); CheckThrow(typeof(ArgumentOutOfRangeException)); wait.Mark(1); } public void CompletingTheWait_WakesTheSlotOnceAndRecordsWhatFired() { TriggerWait wait = Waiting(requiresAll: false, triggers: 3); wait.Mark(2); CheckEqual(new[] { 5 }, woken.ToArray()); CheckEqual(2, wait.Fired); CheckTrue(ReferenceEquals(wait.Triggers[2], wait.Result)); } public void RaiseThatLeavesTheWaitGoing_DoesNotWake() { TriggerWait wait = Waiting(requiresAll: true, triggers: 2); wait.Mark(0); CheckEqual(0, woken.Count); CheckEqual(-1, wait.Fired); CheckNull(wait.Result); CheckEqual(1, wait.Seen); } public void AllOfSeveral_FiresWithTheLastTriggerRaised() { TriggerWait wait = Waiting(requiresAll: true, triggers: 3); wait.Mark(2); wait.Mark(0); wait.Mark(1); CheckEqual(1, wait.Fired); CheckEqual(new[] { 5 }, woken.ToArray()); } public void RaiseAfterTheWaitIsOver_ChangesNothingAndWakesNobody() { TriggerWait wait = Waiting(requiresAll: false, triggers: 3); wait.Mark(0); wait.Mark(2); CheckEqual(0, wait.Fired); CheckEqual(1, wait.Seen); CheckEqual(new[] { 5 }, woken.ToArray()); } public void RaiseOfAnAlreadySeenTrigger_ChangesNothing() { TriggerWait wait = Waiting(requiresAll: true, triggers: 2); wait.Mark(0); wait.Mark(0); CheckEqual(1, wait.Seen); CheckEqual(0, woken.Count); } public void WithoutASlot_ThrowsAndRecordsNothing() { TriggerWait wait = Waiting(requiresAll: false, triggers: 1); wait.Slot = null; CheckThrow(typeof(InvalidOperationException)); wait.Mark(0); } public void WithoutASlot_LeavesTheWaitAsItWas() { TriggerWait wait = Waiting(requiresAll: false, triggers: 1); wait.Slot = null; try { wait.Mark(0); } catch (InvalidOperationException) { } CheckEqual(0, wait.Seen); CheckEqual(-1, wait.Fired); } public void WithoutASlotAfterTheWaitIsOver_DoesNothing() { TriggerWait wait = Waiting(requiresAll: false, triggers: 2); wait.Mark(0); wait.Slot = null; wait.Mark(1); CheckEqual(0, wait.Fired); } } } }