using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnitTestSharp;
namespace Vellum.UnitTests
{
public class DictionaryConverterTests : TestFixture
{
public static SaveSession Session()
{
return SaveConvertersTests.TestConverters().CreateSession();
}
///
/// Saves to Lua text and loads it back.
///
public static Dictionary ThroughLuaText(
Dictionary value)
{
SaveSession session = Session();
SaveNode saved = session.ToNode(value, typeof(Dictionary));
SaveNode node = LuaSaveFormat.Parse(LuaSaveFormat.Format(saved));
return (Dictionary)session.FromNode(node, typeof(Dictionary));
}
public static SaveNode PointNode(double x, double y)
{
return Session().ToNode(new Point(x, y), typeof(Point));
}
public class WriteTests : TestFixture
{
public void Entries_AreSavedAsAMapInTheOrderTheDictionaryEnumeratesThem()
{
var value = new Dictionary { { "b", 2 }, { "a", 1 } };
SaveNode node = Session().ToNode(value, typeof(Dictionary));
IReadOnlyList> entries = node.RequireEntry("entries").RequireMap();
CheckEqual(new[] { "b", "a" }, entries.Select(entry => entry.Key.Text).ToArray());
CheckEqual(new[] { "2", "1" }, entries.Select(entry => entry.Value.Text).ToArray());
}
public void DefaultComparer_IsLeftOut()
{
SaveNode node = Session().ToNode(new Dictionary(), typeof(Dictionary));
CheckEqual(new[] { "entries" }, node.Entries.Keys.ToArray());
}
public void NamedComparer_IsSavedBesideTheEntries()
{
var value = new Dictionary(StringComparer.Ordinal);
SaveNode node = Session().ToNode(value, typeof(Dictionary));
CheckEqual("Ordinal", node.RequireEntry("comparer").Text);
}
public void ComparerThatCantBeSaved_Throws()
{
var value = new Dictionary(new SavedComparerTests.EveryoneEqual());
CheckThrow(typeof(NotSupportedException));
Session().ToNode(value, typeof(Dictionary));
}
public void ConvertedKeys_AreSavedAsTables()
{
var value = new Dictionary { { new Point(1.5, 0), "home" } };
SaveNode node = Session().ToNode(value, typeof(Dictionary));
KeyValuePair entry = node.RequireEntry("entries").RequireMap().Single();
CheckEqual("0x3FF8000000000000", entry.Key.RequireEntry("x").Text);
CheckEqual("home", entry.Value.Text);
}
public void NullValue_IsANullNode()
{
var value = new Dictionary { { "a", null } };
SaveNode node = Session().ToNode(value, typeof(Dictionary));
CheckEqual(SaveNode.Kinds.Null, node.RequireEntry("entries").RequireMap().Single().Value.Kind);
}
public void NullDictionary_IsNull()
{
CheckEqual(SaveNode.Kinds.Null, Session().ToNode(null, typeof(Dictionary)).Kind);
}
}
public class ReadTests : TestFixture
{
public static SaveNode NodeHoldingItself()
{
SaveNode node = SaveNode.NewTable();
SaveNode entries = SaveNode.NewTable();
entries.Entries["self"] = node;
node.Entries[DictionaryConverter.EntriesKey] = entries;
return node;
}
public void DictionaryHoldingItself_ReadsAsADictionaryHoldingItself()
{
var loaded = (Dictionary)new SaveConverters(new SaveConverter[0]).CreateSession()
.FromNode(NodeHoldingItself(), typeof(Dictionary));
CheckTrue(ReferenceEquals(loaded, loaded["self"]));
}
public void TextKeys_RoundTrip()
{
var value = new Dictionary { { "b", 2 }, { "a", 1 } };
Dictionary loaded = ThroughLuaText(value);
CheckEqual(2, loaded.Count);
CheckEqual(1, loaded["a"]);
CheckEqual(2, loaded["b"]);
}
public void KeysThatAreNotIdentifiers_RoundTrip()
{
var value = new Dictionary
{
{ "end", 1 }, { "two words", 2 }, { "", 3 }, { "é\"\n", 4 },
};
Dictionary loaded = ThroughLuaText(value);
CheckEqual(1, loaded["end"]);
CheckEqual(2, loaded["two words"]);
CheckEqual(3, loaded[""]);
CheckEqual(4, loaded["é\"\n"]);
}
public void EmptyDictionary_RoundTrips()
{
CheckEqual(0, ThroughLuaText(new Dictionary()).Count);
}
public void NonTextKeys_RoundTrip()
{
var value = new Dictionary { { 10, "ten" }, { -1, "minus one" } };
Dictionary loaded = ThroughLuaText(value);
CheckEqual("ten", loaded[10]);
CheckEqual("minus one", loaded[-1]);
}
public void ConvertedKeys_RoundTrip()
{
var value = new Dictionary
{
{ new Point(1.5, 0), "home" }, { new Point(0, 2), "mine" },
};
Dictionary loaded = ThroughLuaText(value);
CheckEqual(2, loaded.Count);
CheckEqual("home", loaded[new Point(1.5, 0)]);
CheckEqual("mine", loaded[new Point(0, 2)]);
}
public void ListKeys_RoundTrip()
{
var value = new Dictionary { { new[] { "a", "b" }, 1 } };
Dictionary loaded = ThroughLuaText(value);
CheckEqual(new[] { "a", "b" }, loaded.Keys.Single());
}
public void ValuesThatAreCollections_RoundTrip()
{
var value = new Dictionary> { { "route", new List { new Point(1.5, 0) } } };
Dictionary> loaded = ThroughLuaText(value);
CheckEqual(1.5, loaded["route"][0].X);
}
public void NullValue_RoundTrips()
{
CheckNull(ThroughLuaText(new Dictionary { { "a", null } })["a"]);
}
public void Comparer_RoundTrips()
{
var value = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "a", 1 } };
Dictionary loaded = ThroughLuaText(value);
CheckTrue(loaded.Comparer == StringComparer.OrdinalIgnoreCase);
CheckEqual(1, loaded["A"]);
}
public void NoComparer_LoadsWithTheDefault()
{
Dictionary loaded = ThroughLuaText(new Dictionary { { "a", 1 } });
CheckFalse(loaded.ContainsKey("A"));
}
public void SaveLoadSave_IsIdenticalText()
{
SaveSession session = Session();
var value = new Dictionary
{
{ new Point(1.5, 0), "home" }, { new Point(0, 2), "mine" }, { new Point(3, 3), "far" },
};
string first = LuaSaveFormat.Format(session.ToNode(value, typeof(Dictionary)));
var loaded = (Dictionary)session.FromNode(LuaSaveFormat.Parse(first),
typeof(Dictionary));
string second = LuaSaveFormat.Format(session.ToNode(loaded, typeof(Dictionary)));
CheckEqual(first, second);
}
public void NullForADictionary_IsNull()
{
CheckNull(Session().FromNode(SaveNode.Null, typeof(Dictionary)));
}
public void SameKeyTwice_KeepsTheFirstAndRecordsTheSecond()
{
SaveNode entries = SaveNode.NewMap();
entries.Pairs.Add(new KeyValuePair(PointNode(1, 2), SaveNode.OfText("a")));
entries.Pairs.Add(new KeyValuePair(PointNode(1, 2), SaveNode.OfText("b")));
SaveNode node = SaveNode.NewTable();
node.Entries["entries"] = entries;
SaveSession session = Session();
var loaded = (Dictionary)session.FromNode(node, typeof(Dictionary));
CheckEqual("a", loaded.Single().Value);
CheckEqual(new[] { "entries: [1]" }, SaveConvertersTests.IssuePaths(session));
}
public void KeysTheComparerCallsEqual_KeepsTheFirstAndRecordsTheSecond()
{
SaveNode node = SaveNode.NewTable();
node.Entries["comparer"] = SaveNode.OfText("OrdinalIgnoreCase");
node.Entries["entries"] = SaveNode.NewTable();
node.Entries["entries"].Entries["a"] = SaveNode.OfText("1");
node.Entries["entries"].Entries["A"] = SaveNode.OfText("2");
SaveSession session = Session();
var loaded = (Dictionary)session.FromNode(node, typeof(Dictionary));
CheckEqual(2, loaded["a"]);
CheckEqual(new[] { "entries: [1]" }, SaveConvertersTests.IssuePaths(session));
}
public void MissingEntries_Throws()
{
CheckThrow(typeof(InvalidDataException));
Session().FromNode(SaveNode.NewTable(), typeof(Dictionary));
}
public void NodeThatIsNotATable_Throws()
{
CheckThrow(typeof(InvalidDataException));
Session().FromNode(SaveNode.OfText("3"), typeof(Dictionary));
}
public void NullForAValueType_LeavesTheEntryOutAndRecordsIt()
{
SaveNode node = SaveNode.NewTable();
node.Entries["entries"] = SaveNode.NewTable();
node.Entries["entries"].Entries["a"] = SaveNode.Null;
node.Entries["entries"].Entries["b"] = SaveNode.OfText("2");
SaveSession session = Session();
var loaded = (Dictionary)session.FromNode(node, typeof(Dictionary));
CheckEqual(new[] { "b" }, loaded.Keys.ToArray());
CheckEqual(new[] { "entries: [0]" }, SaveConvertersTests.IssuePaths(session));
}
}
public class TryListChildrenTests : TestFixture
{
public void EachKeyAndValue_AreListedInPairsAsTheirTypes()
{
var value = new Dictionary { { "a", new Waypoint { Name = "x" } }, { "b", null } };
SaveNode node = Session().ToNode(value, typeof(Dictionary));
var children = new ChildList();
CheckTrue(new DictionaryConverter().TryListChildren(node, children));
IReadOnlyList> pairs = node.RequireEntry("entries").RequireMap();
CheckEqual(4, children.Count);
CheckTrue(ReferenceEquals(pairs[0].Key, children.NodeAt(0)));
CheckTrue(ReferenceEquals(pairs[0].Value, children.NodeAt(1)));
CheckTrue(ReferenceEquals(pairs[1].Value, children.NodeAt(3)));
CheckEqual(typeof(string), children.TypeAt(0));
CheckEqual(typeof(Waypoint), children.TypeAt(1));
}
public void TextKeysReadBackFromLuaText_AreListedFromTheTable()
{
var value = new Dictionary { { "a", new Waypoint { Name = "x" } } };
SaveNode node = SaveConvertersTests.ThroughLuaText(
Session().ToNode(value, typeof(Dictionary)));
var children = new ChildList();
CheckTrue(new DictionaryConverter().TryListChildren(node, children));
CheckEqual(2, children.Count);
CheckTrue(ReferenceEquals(node.RequireEntry("entries").RequireEntry("a"), children.NodeAt(1)));
}
public void EmptyDictionary_ListsNothingAndSucceeds()
{
SaveNode node = SaveNode.NewTable();
node.Entries["entries"] = SaveNode.NewMap();
var children = new ChildList();
CheckTrue(new DictionaryConverter().TryListChildren(node, children));
CheckEqual(0, children.Count);
}
public void MissingEntries_ReturnsFalse()
{
CheckFalse(new DictionaryConverter().TryListChildren(
SaveNode.NewTable(), new ChildList()));
}
public void EntriesThatAreNotAMap_ReturnsFalse()
{
SaveNode node = SaveNode.NewTable();
node.Entries["entries"] = SaveNode.OfText("3");
CheckFalse(new DictionaryConverter().TryListChildren(node, new ChildList()));
}
}
public class AllocateTests : TestFixture
{
public void SavedValue_GivesAnEmptyCollection()
{
SaveSession session = SaveConvertersTests.Session();
SaveNode node = session.ToNode(new Dictionary { { 3, "c" }, { 1, "a" } });
CheckEqual(0, new DictionaryConverter().Allocate(node, session).Count);
}
public void NodeOfTheWrongShape_Throws()
{
CheckThrow(typeof(InvalidDataException));
new DictionaryConverter().Allocate(SaveNode.OfText("3"), SaveConvertersTests.Session());
}
}
public class FillTests : TestFixture
{
public void SavedValue_AddsWhatReadLoads()
{
SaveSession session = SaveConvertersTests.Session();
SaveNode node = session.ToNode(new Dictionary { { 3, "c" }, { 1, "a" } });
var converter = new DictionaryConverter();
Dictionary filled = converter.Allocate(node, session);
converter.Fill(filled, node, session);
CheckTrue(converter.Read(node, SaveConvertersTests.Session()).SequenceEqual(filled));
}
}
public class FillNeedsFilledPartTests : TestFixture
{
public void TheHashedOrSortedType_IsTrue()
{
CheckTrue(new DictionaryConverter().FillNeedsFilledPart(typeof(int)));
}
public void AnotherType_IsFalse()
{
CheckFalse(new DictionaryConverter().FillNeedsFilledPart(typeof(string)));
}
}
}
}