using System; using System.Collections.Generic; using System.IO; using System.Linq; using UnitTestSharp; using Vellum; namespace Amphora.Vellum.UnitTests { public class OrderedDictionaryConverterTests : TestFixture { public static SaveSession Session() { return SaveConverters.For(typeof(OrderedDictionaryConverterTests).Assembly).CreateSession(); } public static OrderedDictionary Ordered(IEqualityComparer comparer, params string[] keys) { var returnMe = new OrderedDictionary(comparer); foreach (string key in keys) { returnMe.Add(key, returnMe.Count); } return returnMe; } public static OrderedDictionary ThroughLuaText(OrderedDictionary value) { SaveSession session = Session(); SaveNode node = SaveConverterTests.ThroughLuaText( session.ToNode(value, typeof(OrderedDictionary))); return (OrderedDictionary)session.FromNode(node, typeof(OrderedDictionary)); } public class WriteTests : TestFixture { public void Entries_AreAListOfKeyAndValuePairsInOrder() { SaveNode node = Session().ToNode(Ordered(null, "z", "a", "m"), typeof(OrderedDictionary)); List pairs = node.RequireEntry("entries").Items; CheckEqual(new[] { "z", "a", "m" }, pairs.Select(pair => pair.RequireEntry("key").Text).ToArray()); CheckEqual(new[] { "0", "1", "2" }, pairs.Select(pair => pair.RequireEntry("value").Text).ToArray()); } public void DefaultComparer_IsLeftOut() { SaveNode node = Session().ToNode(Ordered(null, "a"), typeof(OrderedDictionary)); CheckEqual(new[] { "entries" }, node.Entries.Keys.ToArray()); } public void NamedComparer_IsSavedBesideTheEntries() { SaveNode node = Session().ToNode(Ordered(StringComparer.Ordinal, "a"), typeof(OrderedDictionary)); CheckEqual("Ordinal", node.RequireEntry("comparer").Text); } public void ComparerThatCantBeSaved_Throws() { CheckThrow(typeof(NotSupportedException)); Session().ToNode(Ordered(StringComparer.CurrentCulture, "a"), typeof(OrderedDictionary)); } public void NullDictionary_IsNull() { CheckEqual(SaveNode.Kinds.Null, Session().ToNode(null, typeof(OrderedDictionary)).Kind); } } public class ReadTests : TestFixture { public void DictionaryHoldingItself_ReadsAsADictionaryHoldingItself() { SaveNode node = SaveNode.NewTable(); SaveNode pair = SaveNode.NewTable(); pair.Entries[OrderedDictionaryConverter.KeyKey] = SaveNode.OfText("self"); pair.Entries[OrderedDictionaryConverter.ValueKey] = node; SaveNode entries = SaveNode.NewList(); entries.Items.Add(pair); node.Entries[OrderedDictionaryConverter.EntriesKey] = entries; var loaded = (OrderedDictionary)Session().FromNode(node, typeof(OrderedDictionary)); CheckTrue(ReferenceEquals(loaded, loaded["self"])); } public void Order_SurvivesLuaText() { OrderedDictionary loaded = ThroughLuaText(Ordered(null, "z", "a", "m", "b")); CheckEqual(new[] { "z", "a", "m", "b" }, loaded.Keys.ToArray()); CheckEqual(2, loaded["m"]); } public void KeysThatAreNotIdentifiers_RoundTrip() { OrderedDictionary loaded = ThroughLuaText(Ordered(null, "end", "two words", "")); CheckEqual(new[] { "end", "two words", "" }, loaded.Keys.ToArray()); } public void EmptyDictionary_RoundTrips() { CheckEqual(0, ThroughLuaText(Ordered(null)).Count); } public void Comparer_RoundTrips() { OrderedDictionary loaded = ThroughLuaText(Ordered(StringComparer.OrdinalIgnoreCase, "a")); CheckTrue(loaded.Comparer == StringComparer.OrdinalIgnoreCase); CheckEqual(0, loaded["A"]); } public void KeysAndValuesThatAreSaveableTypes_RoundTrip() { SaveSession session = Session(); var value = new OrderedDictionary(); value.Add(new Vector { X = 1.5 }, new[] { "a", null }); value.Add(new Vector { Y = 2 }, null); SaveNode node = SaveConverterTests.ThroughLuaText( session.ToNode(value, typeof(OrderedDictionary))); var loaded = (OrderedDictionary)session.FromNode(node, typeof(OrderedDictionary)); CheckEqual(2, loaded.Count); CheckNull(loaded[new Vector { Y = 2 }]); CheckNull(loaded[new Vector { X = 1.5 }][1]); } public void NullForADictionary_IsNull() { CheckNull(Session().FromNode(SaveNode.Null, typeof(OrderedDictionary))); } public void SameKeyTwice_KeepsTheFirstAndRecordsTheSecond() { SaveNode entries = SaveNode.NewList(); for (int i = 0; i < 2; ++i) { SaveNode pair = SaveNode.NewTable(); pair.Entries["key"] = SaveNode.OfText("a"); pair.Entries["value"] = SaveNode.OfText("1"); entries.Items.Add(pair); } SaveNode node = SaveNode.NewTable(); node.Entries["entries"] = entries; SaveSession session = Session(); var loaded = (OrderedDictionary)session.FromNode(node, typeof(OrderedDictionary)); CheckEqual(1, loaded.Count); CheckEqual(1, session.Sandbox.Issues.Count); } public void PairMissingItsValue_IsLeftOutAndRecorded() { SaveNode pair = SaveNode.NewTable(); pair.Entries["key"] = SaveNode.OfText("a"); SaveNode entries = SaveNode.NewList(); entries.Items.Add(pair); SaveNode node = SaveNode.NewTable(); node.Entries["entries"] = entries; SaveSession session = Session(); var loaded = (OrderedDictionary)session.FromNode(node, typeof(OrderedDictionary)); CheckEqual(0, loaded.Count); CheckEqual(1, session.Sandbox.Issues.Count); } public void MissingEntries_Throws() { CheckThrow(typeof(InvalidDataException)); Session().FromNode(SaveNode.NewTable(), typeof(OrderedDictionary)); } } public class TryListChildrenTests : TestFixture { public void EachKeyAndValue_AreListedInPairsAsTheirTypes() { SaveNode node = Session().ToNode(Ordered(null, "b", "a"), typeof(OrderedDictionary)); var children = new ChildList(); CheckTrue(new OrderedDictionaryConverter().TryListChildren(node, children)); IReadOnlyList pairs = node.RequireEntry("entries").RequireItems(); CheckEqual(4, children.Count); CheckTrue(ReferenceEquals(pairs[0].Entries["key"], children.NodeAt(0))); CheckTrue(ReferenceEquals(pairs[0].Entries["value"], children.NodeAt(1))); CheckTrue(ReferenceEquals(pairs[1].Entries["key"], children.NodeAt(2))); CheckEqual(typeof(string), children.TypeAt(0)); CheckEqual(typeof(int), children.TypeAt(1)); } public void MissingEntries_ReturnsFalse() { CheckFalse(new OrderedDictionaryConverter().TryListChildren( SaveNode.NewTable(), new ChildList())); } public void EntriesThatAreNotAList_ReturnsFalse() { SaveNode node = SaveNode.NewTable(); node.Entries["entries"] = SaveNode.OfText("3"); CheckFalse(new OrderedDictionaryConverter().TryListChildren(node, new ChildList())); } public void PairMissingItsKeyOrValue_ReturnsFalse() { SaveNode pair = SaveNode.NewTable(); pair.Entries["key"] = SaveNode.OfText("a"); SaveNode entries = SaveNode.NewList(); entries.Items.Add(pair); SaveNode node = SaveNode.NewTable(); node.Entries["entries"] = entries; CheckFalse(new OrderedDictionaryConverter().TryListChildren(node, new ChildList())); } public void PairThatIsNotATable_ReturnsFalse() { SaveNode entries = SaveNode.NewList(); entries.Items.Add(SaveNode.OfText("3")); SaveNode node = SaveNode.NewTable(); node.Entries["entries"] = entries; CheckFalse(new OrderedDictionaryConverter().TryListChildren(node, new ChildList())); } } public class AllocateTests : TestFixture { public void SavedValue_GivesAnEmptyDictionaryWithTheSavedComparer() { SaveSession session = Session(); SaveNode node = session.ToNode(Ordered(StringComparer.OrdinalIgnoreCase, "b", "a"), typeof(OrderedDictionary)); OrderedDictionary made = new OrderedDictionaryConverter() .Allocate(node, session); CheckEqual(0, made.Count); CheckEqual(StringComparer.OrdinalIgnoreCase, made.Comparer); } public void NodeWithoutEntries_Throws() { CheckThrow(typeof(InvalidDataException)); new OrderedDictionaryConverter().Allocate(SaveNode.NewTable(), Session()); } } public class FillTests : TestFixture { public void SavedValue_AddsTheEntriesInOrder() { SaveSession session = Session(); SaveNode node = session.ToNode(Ordered(StringComparer.Ordinal, "b", "a"), typeof(OrderedDictionary)); var converter = new OrderedDictionaryConverter(); OrderedDictionary filled = converter.Allocate(node, session); converter.Fill(filled, node, session); CheckEqual(new[] { "b", "a" }, filled.Keys.ToArray()); CheckEqual(1, filled["a"]); } } public class FillNeedsFilledPartTests : TestFixture { public void TheKeyType_IsTrue() { CheckTrue(new OrderedDictionaryConverter().FillNeedsFilledPart(typeof(string))); } public void TheValueType_IsFalse() { CheckFalse(new OrderedDictionaryConverter().FillNeedsFilledPart(typeof(int))); } } } }