using System.IO; using UnitTestSharp; using Vellum; namespace Amphora.Vellum.UnitTests { public class RandConverterTests : TestFixture { public static SaveSession Session() { return SaveConverters.For(typeof(RandConverterTests).Assembly).CreateSession(); } public static Rand ThroughLuaText(Rand value) { SaveSession session = Session(); SaveNode save = SaveNode.NewTable(); save.Entries["value"] = session.ToNode(value, typeof(Rand)); SaveNode read = LuaSaveFormat.Parse(LuaSaveFormat.Format(save)); return (Rand)session.FromNode(read.RequireEntry("value"), typeof(Rand)); } public static SaveNode Saved(string state0, string state1, string state2, string counter) { SaveNode returnMe = SaveNode.NewTable(); returnMe.Entries[RandConverter.State0Key] = SaveNode.OfText(state0); returnMe.Entries[RandConverter.State1Key] = SaveNode.OfText(state1); returnMe.Entries[RandConverter.State2Key] = SaveNode.OfText(state2); returnMe.Entries[RandConverter.CounterKey] = SaveNode.OfText(counter); return returnMe; } public static Rand Loaded(SaveNode node) { return (Rand)Session().FromNode(node, typeof(Rand)); } public class WriteTests : TestFixture { public void SavesTheFourWordsOfTheState() { var rand = new Rand(new Sfc64(state0: 1, state1: 2, state2: 3, counter: 4)); SaveNode node = Session().ToNode(rand, typeof(Rand)); CheckEqual("1", node.RequireEntry("state0").Text); CheckEqual("2", node.RequireEntry("state1").Text); CheckEqual("3", node.RequireEntry("state2").Text); CheckEqual("4", node.RequireEntry("counter").Text); } public void SavesTheStateAsItStandsAfterDraws() { var rand = new Rand(42); var reference = new Sfc64(42); rand.NextUInt64(); reference.NextUInt64(); SaveNode node = Session().ToNode(rand, typeof(Rand)); CheckEqual(reference.Counter.ToString(), node.RequireEntry("counter").Text); } } public class ReadTests : TestFixture { public void SavedState_ResumesTheStream() { Rand loaded = Loaded(Saved("1", "2", "3", "4")); var reference = new Sfc64(state0: 1, state1: 2, state2: 3, counter: 4); CheckEqual(reference.NextUInt64(), loaded.NextUInt64()); CheckEqual(reference.NextUInt64(), loaded.NextUInt64()); } public void RandPartWayThroughItsStream_ContinuesWhereItStopped() { var original = new Rand(42); original.NextUInt64(); original.NextDouble(); Rand loaded = ThroughLuaText(original); CheckEqual(original.NextUInt64(), loaded.NextUInt64()); CheckEqual(original.NextDouble(-3.5, 7.25), loaded.NextDouble(-3.5, 7.25)); } public void LargestWords_SurviveLuaText() { var original = new Rand(new Sfc64(ulong.MaxValue, ulong.MaxValue - 1, 1UL << 63, ulong.MaxValue)); Rand loaded = ThroughLuaText(original); CheckEqual(original.NextUInt64(), loaded.NextUInt64()); CheckEqual(original.NextUInt64(), loaded.NextUInt64()); } public void OneRandHeldTwice_LoadsAsOneRand() { SaveSession saving = Session(); var shared = new Rand(42); SaveNode save = SaveNode.NewTable(); save.Entries["first"] = saving.ToNode(shared, typeof(Rand)); save.Entries["second"] = saving.ToNode(shared, typeof(Rand)); SaveNode read = LuaSaveFormat.Parse(LuaSaveFormat.Format(save)); SaveSession loading = Session(); var first = (Rand)loading.FromNode(read.RequireEntry("first"), typeof(Rand)); var second = (Rand)loading.FromNode(read.RequireEntry("second"), typeof(Rand)); CheckTrue(ReferenceEquals(first, second)); } public void MissingEntry_Throws() { SaveNode node = Saved("1", "2", "3", "4"); node.Entries.Remove("counter"); CheckThrow(typeof(InvalidDataException)); Loaded(node); } public void NegativeWord_LoadsAsZeroAndIsRecordedAsAnIssue() { SaveSession session = Session(); var loaded = (Rand)session.FromNode(Saved("1", "-2", "3", "4"), typeof(Rand)); CheckEqual(0UL, loaded.Generator.State1); CheckEqual(1, session.Sandbox.Issues.Count); } public void WordOfTheWrongShape_IsReportedUnderItsKey() { string message = ""; try { Loaded(Saved("1", "two", "3", "4")); } catch (InvalidDataException exception) { message = exception.Message; } CheckTrue(message.StartsWith("state1: ", System.StringComparison.Ordinal)); } public void NodeThatIsNotATable_Throws() { CheckThrow(typeof(InvalidDataException)); Loaded(SaveNode.OfText("1")); } public void NullForARand_IsNull() { CheckNull(Session().FromNode(SaveNode.Null, typeof(Rand))); } } public class TryListChildrenTests : TestFixture { public void Rand_ListsNothingAndSucceeds() { SaveNode node = Session().ToNode(new Rand(42), typeof(Rand)); var children = new ChildList(); CheckTrue(new RandConverter().TryListChildren(node, children)); CheckEqual(0, children.Count); } public void NodeWithoutState_ReturnsFalse() { CheckFalse(new RandConverter().TryListChildren(SaveNode.NewTable(), new ChildList())); } public void NodeThatIsNotATable_ReturnsFalse() { CheckFalse(new RandConverter().TryListChildren(SaveNode.OfText("3"), new ChildList())); } } } }