using System.IO; using UnitTestSharp; using Vellum; namespace Amphora.Vellum.UnitTests { public class StringViewConverterTests : TestFixture { public static SaveSession Session() { return SaveConverters.For(typeof(StringViewConverterTests).Assembly).CreateSession(); } public static StringView ThroughLuaText(StringView value) { SaveSession session = Session(); SaveNode save = SaveNode.NewTable(); save.Entries["value"] = session.ToNode(value, typeof(StringView)); SaveNode read = LuaSaveFormat.Parse(LuaSaveFormat.Format(save)); return (StringView)session.FromNode(read.RequireEntry("value"), typeof(StringView)); } /// /// Returns a saved view of running from to /// . /// public static SaveNode Saved(string text, string startIndex, string endIndex) { SaveNode returnMe = SaveNode.NewTable(); returnMe.Entries[StringViewConverter.TextKey] = SaveNode.OfText(text); returnMe.Entries[StringViewConverter.StartIndexKey] = SaveNode.OfText(startIndex); returnMe.Entries[StringViewConverter.EndIndexKey] = SaveNode.OfText(endIndex); return returnMe; } public static StringView Loaded(SaveNode node) { return (StringView)Session().FromNode(node, typeof(StringView)); } public class WriteTests : TestFixture { public void WholeString_IsTheStringAndItsFullRange() { SaveNode node = Session().ToNode(new StringView("hello"), typeof(StringView)); CheckEqual("hello", node.RequireEntry("text").Text); CheckEqual("0", node.RequireEntry("startIndex").Text); CheckEqual("5", node.RequireEntry("endIndex").Text); } public void ViewOfPartOfAString_IsTheWholeStringAndWhereItRuns() { SaveNode node = Session().ToNode(new StringView("hello world", 6, 11), typeof(StringView)); CheckEqual("hello world", node.RequireEntry("text").Text); CheckEqual("6", node.RequireEntry("startIndex").Text); CheckEqual("11", node.RequireEntry("endIndex").Text); } public void EmptyView_KeepsItsPlaceInTheString() { SaveNode node = Session().ToNode(new StringView("hello", 2, 2), typeof(StringView)); CheckEqual("hello", node.RequireEntry("text").Text); CheckEqual("2", node.RequireEntry("startIndex").Text); CheckEqual("2", node.RequireEntry("endIndex").Text); } public void DefaultView_IsAViewOfAnEmptyString() { SaveNode node = Session().ToNode(default(StringView), typeof(StringView)); CheckEqual("", node.RequireEntry("text").Text); CheckEqual("0", node.RequireEntry("startIndex").Text); CheckEqual("0", node.RequireEntry("endIndex").Text); } public void ViewsOfOneString_ShareTheNodeOfThatString() { SaveSession session = Session(); string text = new string('s', 4); SaveNode whole = session.ToNode(new StringView(text), typeof(StringView)); SaveNode part = session.ToNode(new StringView(text, 1, 3), typeof(StringView)); SaveNode plain = session.ToNode(text, typeof(string)); CheckTrue(ReferenceEquals(plain, whole.RequireEntry("text"))); CheckTrue(ReferenceEquals(plain, part.RequireEntry("text"))); } public void ViewsOfEqualStringsThatAreTwoObjects_DoNotShare() { SaveSession session = Session(); SaveNode first = session.ToNode(new StringView(new string('s', 4)), typeof(StringView)); SaveNode second = session.ToNode(new StringView(new string('s', 4)), typeof(StringView)); CheckFalse(ReferenceEquals(first.RequireEntry("text"), second.RequireEntry("text"))); } } public class ReadTests : TestFixture { public void SavedView_KeepsItsTextAndRange() { StringView loaded = Loaded(Saved("hello world", "6", "11")); CheckEqual("hello world", loaded.Text); CheckEqual(6, loaded.StartIndex); CheckEqual(11, loaded.EndIndex); CheckEqual("world", loaded.ToString()); } public void ViewOfPartOfAString_RoundTripsWithItsPlace() { var original = new StringView("hello world", 6, 11); StringView loaded = ThroughLuaText(original); CheckTrue(original == loaded); CheckEqual(6, loaded.StartIndex); CheckEqual(11, loaded.EndIndex); } public void DefaultView_LoadsAsAViewOfAnEmptyString() { StringView loaded = ThroughLuaText(default(StringView)); CheckEqual("", loaded.Text); CheckEqual(0, loaded.Length); } public void AwkwardCharacters_SurviveLuaText() { var original = new StringView("say \"hi\"\r\n\ttab \\ end", 4, 8); CheckEqual(original.Text, ThroughLuaText(original).Text); CheckEqual(original.ToString(), ThroughLuaText(original).ToString()); } public void ViewsOfOneStringSavedInAFile_LoadOverOneString() { SaveSession saving = Session(); string text = new string('s', 6); SaveNode save = SaveNode.NewTable(); save.Entries["text"] = saving.ToNode(text, typeof(string)); save.Entries["first"] = saving.ToNode(new StringView(text, 0, 2), typeof(StringView)); save.Entries["second"] = saving.ToNode(new StringView(text, 3, 6), typeof(StringView)); SaveNode read = LuaSaveFormat.Parse(LuaSaveFormat.Format(save)); SaveSession loading = Session(); var loadedText = (string)loading.FromNode(read.RequireEntry("text"), typeof(string)); var first = (StringView)loading.FromNode(read.RequireEntry("first"), typeof(StringView)); var second = (StringView)loading.FromNode(read.RequireEntry("second"), typeof(StringView)); CheckTrue(ReferenceEquals(loadedText, first.Text)); CheckTrue(ReferenceEquals(loadedText, second.Text)); CheckEqual(3, second.Length); } public void EndBeforeStart_Throws() { CheckThrow(typeof(InvalidDataException)); Loaded(Saved("hello", "4", "2")); } public void IndexPastTheText_Throws() { CheckThrow(typeof(InvalidDataException)); Loaded(Saved("hello", "0", "6")); } public void NegativeIndex_Throws() { CheckThrow(typeof(InvalidDataException)); Loaded(Saved("hello", "-1", "2")); } public void MissingEntry_Throws() { SaveNode node = Saved("hello", "0", "5"); node.Entries.Remove("endIndex"); CheckThrow(typeof(InvalidDataException)); Loaded(node); } public void IndexOfTheWrongShape_IsReportedUnderItsKey() { string message = ""; try { Loaded(Saved("hello", "one", "5")); } catch (InvalidDataException exception) { message = exception.Message; } CheckTrue(message.StartsWith("startIndex: ", System.StringComparison.Ordinal)); } public void NullText_Throws() { SaveNode node = Saved("hello", "0", "5"); node.Entries["text"] = SaveNode.Null; CheckThrow(typeof(InvalidDataException)); Loaded(node); } public void NodeThatIsNotATable_Throws() { CheckThrow(typeof(InvalidDataException)); Loaded(SaveNode.OfText("hello")); } public void NullForAStringView_Throws() { CheckThrow(typeof(InvalidDataException)); Session().FromNode(SaveNode.Null, typeof(StringView)); } public void NullForANullableStringView_IsNull() { CheckNull(Session().FromNode(SaveNode.Null, typeof(StringView?))); } } public class TryListChildrenTests : TestFixture { public void StringView_ListsNothingAndSucceeds() { SaveNode node = Session().ToNode(new StringView("hello", 1, 3), typeof(StringView)); var children = new ChildList(); CheckTrue(new StringViewConverter().TryListChildren(node, children)); CheckEqual(0, children.Count); } public void NodeWithoutText_ReturnsFalse() { CheckFalse(new StringViewConverter().TryListChildren(SaveNode.NewTable(), new ChildList())); } public void NodeThatIsNotATable_ReturnsFalse() { CheckFalse(new StringViewConverter().TryListChildren(SaveNode.OfText("3"), new ChildList())); } } } }