using Amphora; using System; using System.Collections.Generic; using UnitTestSharp; namespace Ariadne.UnitTests { public class FrameTests : TestFixture { public class ResumeKeyTests : TestFixture { private Frame frame; public override void TestSetup() { frame = new Frame(); } public void EmptyCursor_IsNull() { CheckNull(frame.ResumeKey); } public void DepthWithinTheCursor_IsTheKeyThere() { frame.Cursor.AddRange(new[] { "outer", "inner" }); frame.Depth = 1; CheckEqual("inner", frame.ResumeKey); } public void DepthPastTheCursor_IsNull() { frame.Cursor.Add("outer"); frame.Depth = 1; CheckNull(frame.ResumeKey); } } public class MarkTests : TestFixture { private Frame frame; public override void TestSetup() { frame = new Frame(); } public void PastTheCursor_AppendsTheKey() { frame.Mark("wait"); CheckEqual(new[] { "wait" }, frame.Cursor); } public void WithinTheCursor_ReplacesTheKeyAndDropsDeeperOnes() { frame.Cursor.AddRange(new[] { "outer", "inner", "innermost" }); frame.Depth = 1; frame.Mark("elsewhere"); CheckEqual(new[] { "outer", "elsewhere" }, frame.Cursor); } } public class EnterTests : TestFixture { private Frame frame; public override void TestSetup() { frame = new Frame(); } public void PastTheCursor_AppendsTheKeyAndGoesDeeper() { frame.Enter("act"); CheckEqual(new[] { "act" }, frame.Cursor); CheckEqual(1, frame.Depth); } public void TheKeyAlreadyThere_KeepsTheKeysBelowIt() { frame.Cursor.AddRange(new[] { "act", "wait" }); frame.Enter("act"); CheckEqual(new[] { "act", "wait" }, frame.Cursor); CheckEqual(1, frame.Depth); } public void ADifferentKey_ReplacesItAndDropsDeeperOnes() { frame.Cursor.AddRange(new[] { "act", "wait" }); frame.Enter("other"); CheckEqual(new[] { "other" }, frame.Cursor); CheckEqual(1, frame.Depth); } } public class PassageTests : TestFixture { public void Dispose_ReturnsToTheOuterDepth() { var frame = new Frame(); Frame.Passage passage = frame.Enter("act"); passage.Dispose(); CheckEqual(0, frame.Depth); } } public class LendTests : TestFixture { public void Callee_SharesThePathAndDepth() { var lender = new Frame(); lender.Cursor.Add("outer"); lender.Depth = 1; var callee = new Frame(); CheckTrue(ReferenceEquals(callee, lender.Lend(callee))); CheckTrue(ReferenceEquals(lender.Cursor, callee.Cursor)); CheckEqual(1, callee.Depth); } public void CalleesKeys_JoinTheLendersPath() { var lender = new Frame(); lender.Cursor.Add("outer"); lender.Depth = 1; lender.Lend(new Frame()).Mark("inner"); CheckEqual(new[] { "outer", "inner" }, lender.Cursor); } public void Callee_SharesTheWakeSlot() { var lender = new Frame { Wake = new WakeSlot() }; var callee = lender.Lend(new Frame()); CheckTrue(ReferenceEquals(lender.Wake, callee.Wake)); } public void CalleeWithoutAWakeSlotOnTheLender_HasNone() { var callee = new Frame().Lend(new Frame { Wake = new WakeSlot() }); CheckNull(callee.Wake); } public void CalleesSleep_ReachesTheLendersSlot() { var lender = new Frame { Wake = new WakeSlot() }; lender.Lend(new Frame()).Sleep(TimeSpan.FromSeconds(3)); CheckTrue(lender.Wake.Sleeping); CheckEqual(Duration.FromSeconds(3), lender.Wake.Deadline); } } public class SleepTests : TestFixture { public void WithAWakeSlot_RecordsTheDeadline() { var frame = new Frame { Wake = new WakeSlot() }; frame.Sleep(TimeSpan.FromSeconds(5)); CheckTrue(frame.Wake.Sleeping); CheckEqual(Duration.FromSeconds(5), frame.Wake.Deadline); } public void LaterSleep_ReplacesTheDeadline() { var frame = new Frame { Wake = new WakeSlot() }; frame.Sleep(TimeSpan.FromSeconds(5)); frame.Sleep(TimeSpan.FromSeconds(8)); CheckEqual(Duration.FromSeconds(8), frame.Wake.Deadline); } public void WithoutAWakeSlot_DoesNothing() { var frame = new Frame(); frame.Sleep(TimeSpan.FromSeconds(5)); CheckNull(frame.Wake); } } public class SuspendTests : TestFixture { public void WithAWakeSlot_MarksItSuspended() { var frame = new Frame { Wake = new WakeSlot() }; frame.Suspend(); CheckTrue(frame.Wake.Suspended); CheckFalse(frame.Wake.Sleeping); } public void WithoutAWakeSlot_DoesNothing() { var frame = new Frame(); frame.Suspend(); CheckNull(frame.Wake); } public void CalleesSuspend_ReachesTheLendersSlot() { var lender = new Frame { Wake = new WakeSlot() }; lender.Lend(new Frame()).Suspend(); CheckTrue(lender.Wake.Suspended); } } public class RequireWakeTests : TestFixture { public void WithAWakeSlot_ReturnsIt() { var slot = new WakeSlot(); var frame = new Frame { Wake = slot }; CheckTrue(ReferenceEquals(slot, frame.RequireWake())); } public void WithoutAWakeSlot_Throws() { CheckThrow(typeof(InvalidOperationException)); new Frame().RequireWake(); } public void Callee_ReturnsTheLendersSlot() { var slot = new WakeSlot(); var lender = new Frame { Wake = slot }; CheckTrue(ReferenceEquals(slot, lender.Lend(new Frame()).RequireWake())); } } public class LocalsTests : TestFixture { public void SaveLocal_ThrowsForAKeyNoFrameHolds() { CheckThrow(typeof(InvalidOperationException)); new Frame().SaveLocal("Run.ghost", new ArcRecord()); } public void LoadLocals_ChangesNothing() { var record = new ArcRecord(); record.Locals.Add("Run.ghost", 1); new Frame().LoadLocals(record); CheckEqual(1, record.Locals.Count); } } public class ExitTests : TestFixture { private Frame frame; public override void TestSetup() { frame = new Frame(); } public void WithinTheCursor_DropsTheRunningPassagesKeysAndDeeperOnes() { frame.Cursor.AddRange(new[] { "outer", "inner", "innermost" }); frame.Depth = 1; frame.Exit(); CheckEqual(new[] { "outer" }, frame.Cursor); } public void PastTheCursor_ChangesNothing() { frame.Cursor.Add("outer"); frame.Depth = 1; frame.Exit(); CheckEqual(new[] { "outer" }, frame.Cursor); } } } }