using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using Ariadne.UnitTests;
using UnitTestSharp;
using Vellum;
namespace Ariadne.Vellum.UnitTests
{
public class ArcRecordTests : TestFixture
{
public static SaveSession Session()
{
return SaveConverters.For(typeof(ArcRecordTests).Assembly).CreateSession();
}
public static ArcRecord SampleRecord()
{
var returnMe = new ArcRecord(Session()) { Cursor = { "act2", "build" }, Finished = true };
returnMe.Fields.Entries["alpha"] = SaveNode.OfText("first");
returnMe.Fields.Entries["middle"] = SaveNode.Null;
returnMe.Locals.Entries["Run.waits"] = SaveNode.OfText("2");
return returnMe;
}
///
/// Returns a script that has paused twice, with a count of 2 in both its field and its local.
///
public static CountingScript PausedTwice()
{
var returnMe = new CountingScript();
var gates = new Gates();
returnMe.Tick(gates, TestTicks.Fresh());
returnMe.Tick(gates, TestTicks.Fresh());
return returnMe;
}
public static string Saved(Arc arc)
{
return LuaSaveFormat.Format(Session().ToNode(arc, arc.GetType()));
}
public static ArcType Load(string save)
where ArcType : class
{
return (ArcType)Session().FromNode(LuaSaveFormat.Parse(save), typeof(ArcType));
}
public class CursorTests : TestFixture
{
public void SetsTheCursor()
{
var record = new ArcRecord(Session());
((IArcWriter)record).Cursor(new[] { "act2", "build" });
CheckEqual(new[] { "act2", "build" }, record.Cursor);
}
public void CopiesTheLabels()
{
var labels = new List { "act2" };
var record = new ArcRecord(Session());
((IArcWriter)record).Cursor(labels);
labels.Add("build");
CheckEqual(new[] { "act2" }, record.Cursor);
}
}
public class FinishedTests : TestFixture
{
public void SetsFinished()
{
var record = new ArcRecord(Session());
((IArcWriter)record).Finished(true);
CheckTrue(record.Finished);
}
}
public class FieldTests : TestFixture
{
public void WritesThroughTheConverters()
{
var record = new ArcRecord(Session());
record.Field("At", new Point(1.5, 0));
CheckEqual("0x3FF8000000000000", record.Fields.Entries["At"].RequireEntry("x").Text);
}
public void SecondFieldWithOneKey_Throws()
{
var record = new ArcRecord(Session());
record.Field("Count", 1);
CheckThrow(typeof(ArgumentException));
record.Field("Count", 2);
}
public void TypeThatCantBeSaved_Throws()
{
CheckThrow(typeof(NotSupportedException));
#pragma warning disable VEL0004 // The build-time check would stop this, but the runtime has to catch it too.
new ArcRecord(Session()).Field("Visited", new System.Collections.ObjectModel.Collection());
#pragma warning restore VEL0004
}
}
public class LocalTests : TestFixture
{
public void WritesThroughTheConverters()
{
var record = new ArcRecord(Session());
record.Local("Run.start", new Point(1.5, 0));
CheckEqual("0x3FF8000000000000", record.Locals.Entries["Run.start"].RequireEntry("x").Text);
}
public void SecondLocalWithOneKey_Throws()
{
var record = new ArcRecord(Session());
record.Local("Run.waits", 1);
CheckThrow(typeof(ArgumentException));
record.Local("Run.waits", 2);
}
}
public class LocalKeysTests : TestFixture
{
public void ListsEverySavedLocal()
{
CheckEqual(new[] { "Run.waits" }, SampleRecord().LocalKeys);
}
public void LeavesOutTheCallsTables()
{
ArcRecord record = SampleRecord();
record.Scope("Run.first/");
CheckEqual(new[] { "Run.waits" }, record.LocalKeys);
}
}
public class ScopeNamesTests : TestFixture
{
public void ListsEveryCallsTableAndNoLocal()
{
ArcRecord record = SampleRecord();
record.Scope("Run.first/");
record.Scope("Run.second/");
CheckEqual(new[] { "Run.first/", "Run.second/" }, record.ScopeNames);
}
}
public class ScopeTests : TestFixture
{
public void WritesLocalsInATableAmongTheLocalsNamedForTheCall()
{
var record = new ArcRecord(Session());
record.Scope("Run.first/").Local("Step.count", 4);
CheckEqual(new[] { "Run.first/" }, record.Locals.Entries.Keys);
CheckEqual("4", record.Locals.RequireEntry("Run.first/").RequireEntry("Step.count").Text);
}
public void WritesLocalsThroughTheConverters()
{
var record = new ArcRecord(Session());
record.Scope("Run.first/").Local("Step.start", new Point(1.5, 0));
CheckEqual("0x3FF8000000000000",
record.Locals.RequireEntry("Run.first/").RequireEntry("Step.start").RequireEntry("x").Text);
}
public void SecondCallWithOneName_Throws()
{
var record = new ArcRecord(Session());
record.Scope("Run.first/");
CheckThrow(typeof(ArgumentException));
record.Scope("Run.first/");
}
public void SecondLocalWithOneKeyInACall_Throws()
{
IArcWriter scope = new ArcRecord(Session()).Scope("Run.first/");
scope.Local("Step.count", 1);
CheckThrow(typeof(ArgumentException));
scope.Local("Step.count", 2);
}
public void CallInsideACall_IsATableInsideThatCallsTable()
{
var record = new ArcRecord(Session());
record.Scope("Run.first/").Scope("Step.second/").Local("Inner.count", 3);
CheckEqual("3", record.Locals.RequireEntry("Run.first/").RequireEntry("Step.second/")
.RequireEntry("Inner.count").Text);
}
public void CursorFinishedAndFields_GoToTheArcItself()
{
var record = new ArcRecord(Session());
IArcWriter scope = record.Scope("Run.first/");
scope.Cursor(new[] { "first", "wait" });
scope.Finished(true);
scope.Field("Count", 7);
CheckEqual(new[] { "first", "wait" }, record.Cursor);
CheckTrue(record.Finished);
CheckEqual("7", record.Fields.RequireEntry("Count").Text);
}
}
public class TryScopeTests : TestFixture
{
public static ArcRecord WithACall()
{
var written = new ArcRecord(Session());
written.Field("Count", 5);
IArcWriter call = written.Scope("Run.first/");
call.Local("Step.count", 4);
call.Scope("Step.second/").Local("Inner.count", 3);
return ArcRecord.FromNode(written.ToNode(), Session());
}
public void SavedCall_IsReadThroughTheConverters()
{
IArcReader scope;
int count;
CheckTrue(WithACall().TryScope("Run.first/", out scope));
CheckTrue(scope.TryLocal("Step.count", out count));
CheckEqual(4, count);
}
public void MissingCall_IsFalse()
{
IArcReader scope;
CheckFalse(WithACall().TryScope("Run.other/", out scope));
CheckNull(scope);
}
public void CallThatIsNotATable_IsFalse()
{
var record = new ArcRecord(Session());
record.Locals.Entries["Run.first/"] = SaveNode.OfText("x");
IArcReader scope;
CheckFalse(record.TryScope("Run.first/", out scope));
}
public void CallInsideACall_IsRead()
{
IArcReader scope;
IArcReader inner;
int count;
CheckTrue(WithACall().TryScope("Run.first/", out scope));
CheckTrue(scope.TryScope("Step.second/", out inner));
CheckTrue(inner.TryLocal("Inner.count", out count));
CheckEqual(3, count);
}
public void CallsLocalKeysAndScopeNames_LeaveOutEachOther()
{
IArcReader scope;
CheckTrue(WithACall().TryScope("Run.first/", out scope));
CheckEqual(new[] { "Step.count" }, scope.LocalKeys);
CheckEqual(new[] { "Step.second/" }, scope.ScopeNames);
}
public void MissingLocalInACall_IsFalse()
{
IArcReader scope;
int count;
CheckTrue(WithACall().TryScope("Run.first/", out scope));
CheckFalse(scope.TryLocal("Step.removed", out count));
}
public void CallReadsTheArcsCursorFinishedAndFields()
{
var written = new ArcRecord(Session()) { Cursor = { "first", "wait" }, Finished = true };
written.Field("Count", 5);
written.Scope("Run.first/");
ArcRecord record = ArcRecord.FromNode(written.ToNode(), Session());
IArcReader scope;
int count;
CheckTrue(record.TryScope("Run.first/", out scope));
CheckEqual(new[] { "first", "wait" }, scope.Cursor);
CheckTrue(scope.Finished);
CheckTrue(scope.TryField("Count", out count));
CheckEqual(5, count);
}
public void PublishingFromACall_HandsTheArcToAnythingLoadingThatNode()
{
SaveSession session = Session();
SaveNode node = SampleRecord().ToNode();
ArcRecord record = ArcRecord.FromNode(node, session);
record.Locals.Entries["Run.first/"] = SaveNode.NewTable();
IArcReader scope;
var published = new Waypoint();
CheckTrue(record.TryScope("Run.first/", out scope));
scope.Publish(published);
CheckTrue(ReferenceEquals(published, session.FromNode(node, typeof(Waypoint))));
}
}
public class TryFieldTests : TestFixture
{
public void SavedField_IsReadThroughTheConverters()
{
var record = new ArcRecord(Session());
record.Field("At", new Point(1.5, -2));
Point at;
CheckTrue(record.TryField("At", out at));
CheckEqual(-2.0, at.Y);
}
public void MissingField_IsFalse()
{
int count;
CheckFalse(new ArcRecord(Session()).TryField("Count", out count));
CheckEqual(0, count);
}
public void ValueOfTheWrongShape_IsFalse()
{
Point at;
CheckFalse(SampleRecord().TryField("alpha", out at));
}
}
public class HasFieldTests : TestFixture
{
public void SavedField_IsTrue()
{
var record = new ArcRecord(Session());
record.Field("Count", 5);
CheckTrue(record.HasField("Count"));
}
public void MissingField_IsFalse()
{
CheckFalse(new ArcRecord(Session()).HasField("Count"));
}
public void ValueOfTheWrongShape_IsTrue()
{
CheckTrue(SampleRecord().HasField("alpha"));
}
public void CallReadsTheArcsFields()
{
IArcReader scope;
CheckTrue(TryScopeTests.WithACall().TryScope("Run.first/", out scope));
CheckTrue(scope.HasField("Count"));
CheckFalse(scope.HasField("removed"));
}
}
public class TryLocalTests : TestFixture
{
public void SavedLocal_IsRead()
{
int waits;
CheckTrue(SampleRecord().TryLocal("Run.waits", out waits));
CheckEqual(2, waits);
}
public void MissingLocal_IsFalse()
{
int waits;
CheckFalse(SampleRecord().TryLocal("Run.removed", out waits));
}
}
public class RegistrationTests : TestFixture
{
public void FieldsAndLocals_AreRegisteredAsSavingAndLoadingTheirTypeArgument()
{
List methods = typeof(ArcRecord).Assembly.GetCustomAttributes()
.Where(attribute => attribute.Method.StartsWith("M:Ariadne.Vellum.ArcRecord.",
System.StringComparison.Ordinal) && attribute.Saved == typeof(SaveMethodParameter0))
.Select(attribute => attribute.Method)
.ToList();
CheckEqualCommutative(new[]
{
"M:Ariadne.Vellum.ArcRecord.Field``1(System.String,``0)",
"M:Ariadne.Vellum.ArcRecord.Local``1(System.String,``0)",
"M:Ariadne.Vellum.ArcRecord.TryField``1(System.String,``0@)",
"M:Ariadne.Vellum.ArcRecord.TryLocal``1(System.String,``0@)",
}, methods);
}
}
public class PublishTests : TestFixture
{
public void RecordBeingWritten_Throws()
{
CheckThrow(typeof(InvalidOperationException));
new ArcRecord(Session()).Publish(new object());
}
public void Null_Throws()
{
ArcRecord record = ArcRecord.FromNode(SampleRecord().ToNode(), Session());
CheckThrow(typeof(ArgumentNullException));
record.Publish(null);
}
public void RecordReadFromANode_HandsTheArcToAnythingLoadingThatNode()
{
SaveSession session = Session();
SaveNode node = SampleRecord().ToNode();
ArcRecord record = ArcRecord.FromNode(node, session);
var published = new Waypoint();
record.Publish(published);
CheckTrue(ReferenceEquals(published, session.FromNode(node, typeof(Waypoint))));
}
}
public class ToNodeTests : TestFixture
{
public void SharesTheRecordsTablesRatherThanCopying()
{
ArcRecord record = SampleRecord();
SaveNode node = record.ToNode();
CheckEqual(record.Fields, node.RequireEntry(ArcRecord.FieldsKey));
CheckEqual(record.Locals, node.RequireEntry(ArcRecord.LocalsKey));
}
public void WritesCursorFinishedFieldsAndLocals()
{
SaveNode node = SampleRecord().ToNode();
CheckEqual(4, node.Entries.Count);
CheckEqual(new[] { "act2", "build" },
node.RequireEntry(ArcRecord.CursorKey).RequireItems().Select(label => label.Text).ToArray());
CheckEqual("true", node.RequireEntry(ArcRecord.FinishedKey).Text);
SaveNode fields = node.RequireEntry(ArcRecord.FieldsKey);
CheckEqual(2, fields.Entries.Count);
CheckEqual("first", fields.RequireEntry("alpha").Text);
CheckEqual(SaveNode.Kinds.Null, fields.RequireEntry("middle").Kind);
SaveNode locals = node.RequireEntry(ArcRecord.LocalsKey);
CheckEqual(1, locals.Entries.Count);
CheckEqual("2", locals.RequireEntry("Run.waits").Text);
}
public void NullLabel_Throws()
{
var record = new ArcRecord(Session()) { Cursor = { "act2", null } };
CheckThrow(typeof(ArgumentNullException));
record.ToNode();
}
public void FreshRecord_IsUnfinishedWithAnEmptyCursorAndEmptyTables()
{
SaveNode node = new ArcRecord(Session()).ToNode();
CheckEqual(SaveNode.Kinds.List, node.RequireEntry(ArcRecord.CursorKey).Kind);
CheckEqual(0, node.RequireEntry(ArcRecord.CursorKey).Items.Count);
CheckEqual("false", node.RequireEntry(ArcRecord.FinishedKey).Text);
CheckEqual(0, node.RequireEntry(ArcRecord.FieldsKey).Entries.Count);
CheckEqual(0, node.RequireEntry(ArcRecord.LocalsKey).Entries.Count);
}
}
public class FromNodeTests : TestFixture
{
public void SharesTheNodesTablesRatherThanCopying()
{
SaveNode node = SampleRecord().ToNode();
ArcRecord record = ArcRecord.FromNode(node, Session());
CheckEqual(node.RequireEntry(ArcRecord.FieldsKey), record.Fields);
CheckEqual(node.RequireEntry(ArcRecord.LocalsKey), record.Locals);
}
public void ReadsWhatToNodeWrote()
{
ArcRecord record = ArcRecord.FromNode(SampleRecord().ToNode(), Session());
CheckEqual(new[] { "act2", "build" }, record.Cursor);
CheckTrue(record.Finished);
CheckEqual(2, record.Fields.Entries.Count);
CheckEqual("first", record.Fields.Entries["alpha"].Text);
CheckEqual(SaveNode.Kinds.Null, record.Fields.Entries["middle"].Kind);
CheckEqual(1, record.Locals.Entries.Count);
CheckEqual("2", record.Locals.Entries["Run.waits"].Text);
}
public void EmptyTable_GivesAFreshRecord()
{
ArcRecord record = ArcRecord.FromNode(SaveNode.NewTable(), Session());
CheckEqual(0, record.Cursor.Count);
CheckFalse(record.Finished);
CheckEqual(0, record.Fields.Entries.Count);
CheckEqual(0, record.Locals.Entries.Count);
}
public void NonTable_Throws()
{
CheckThrow(typeof(InvalidDataException));
ArcRecord.FromNode(SaveNode.OfText("act2"), Session());
}
public void LabelsContainingDotsOrNothing_SurviveALuaRoundTrip()
{
var record = new ArcRecord(Session()) { Cursor = { "act2.build", "", "last" } };
SaveNode node = LuaSaveFormat.Parse(LuaSaveFormat.Format(record.ToNode()));
CheckEqual(new[] { "act2.build", "", "last" }, ArcRecord.FromNode(node, Session()).Cursor);
}
public void EmptyTableCursor_IsAnEmptyCursor()
{
SaveNode node = SaveNode.NewTable();
node.Entries[ArcRecord.CursorKey] = SaveNode.NewTable();
CheckEqual(0, ArcRecord.FromNode(node, Session()).Cursor.Count);
}
public void CursorAsText_Throws()
{
SaveNode node = SaveNode.NewTable();
node.Entries[ArcRecord.CursorKey] = SaveNode.OfText("act2.build");
CheckThrow(typeof(InvalidDataException));
ArcRecord.FromNode(node, Session());
}
public void NonTextLabel_Throws()
{
SaveNode cursor = SaveNode.NewList();
cursor.Items.Add(SaveNode.OfText("act2"));
cursor.Items.Add(SaveNode.Null);
SaveNode node = SaveNode.NewTable();
node.Entries[ArcRecord.CursorKey] = cursor;
CheckThrow(typeof(InvalidDataException));
ArcRecord.FromNode(node, Session());
}
public void FinishedInAnyCase_IsRead()
{
SaveNode node = SaveNode.NewTable();
node.Entries[ArcRecord.FinishedKey] = SaveNode.OfText("True");
CheckTrue(ArcRecord.FromNode(node, Session()).Finished);
}
public void FinishedOtherThanABool_IsNotFinishedAndRecordedUnderItsKey()
{
SaveNode node = SaveNode.NewTable();
node.Entries[ArcRecord.FinishedKey] = SaveNode.OfText("yes");
SaveSession session = Session();
CheckFalse(ArcRecord.FromNode(node, session).Finished);
CheckEqual(new[] { "finished" }, session.Sandbox.Issues.Select(issue => issue.Path).ToArray());
}
public void NonTextFinished_IsNotFinishedAndRecorded()
{
SaveNode node = SaveNode.NewTable();
node.Entries[ArcRecord.FinishedKey] = SaveNode.NewTable();
SaveSession session = Session();
CheckFalse(ArcRecord.FromNode(node, session).Finished);
CheckEqual(1, session.Sandbox.Issues.Count);
}
public void NonTableFields_Throws()
{
SaveNode node = SaveNode.NewTable();
node.Entries[ArcRecord.FieldsKey] = SaveNode.OfText("none");
CheckThrow(typeof(InvalidDataException));
ArcRecord.FromNode(node, Session());
}
public void NonTableLocals_Throws()
{
SaveNode node = SaveNode.NewTable();
node.Entries[ArcRecord.LocalsKey] = SaveNode.OfText("none");
CheckThrow(typeof(InvalidDataException));
ArcRecord.FromNode(node, Session());
}
}
public class SaveTests : TestFixture
{
public void WritesTheArcAsOneLuaTable()
{
string expected =
"return {\n" +
" cursor = { \"wait\" },\n" +
" fields = {\n" +
" Count = \"2\",\n" +
" Note = \"initial\",\n" +
" },\n" +
" finished = \"false\",\n" +
" locals = {\n" +
" [\"Run.waits\"] = \"2\",\n" +
" },\n" +
"}\n";
CheckEqual(expected, Saved(PausedTwice()));
}
public void ListHeldByAFieldAndALocal_IsWrittenOnceAndReferredToTwice()
{
var script = new SharingScript();
script.Route.Add(new Waypoint { Name = "start" });
script.Tick(new Gates(), TestTicks.Fresh());
string save = Saved(script);
CheckTrue(save.Contains("fill(shared[1], {"));
CheckTrue(save.Contains("Route = shared[1],"));
CheckTrue(save.Contains("[\"Run.kept\"] = shared[1],"));
}
public void CallsLocals_AreWrittenAsATableInsideTheLocalsNamedForTheCall()
{
string save = Saved(ForeignCallSaveTests.PausedInside(new Gates(), ticks: 2));
CheckTrue(save.Contains("[\"Run.update/\"] = {"));
CheckTrue(save.Contains("[\"Update.waited\"] = \"2\","));
}
public void ConvertedFieldsAndLocals_UseTheConvertersTheArcsAssemblyNames()
{
var script = new ConvertedScript();
script.Tick(new Gates(), TestTicks.Fresh());
script.Destination = new Waypoint { Name = "midway", At = new Point(3, 4) };
string save = Saved(script);
CheckTrue(save.Contains("[\"Run.start\"] = {"));
CheckTrue(save.Contains("name = \"midway\","));
}
}
public class LoadTests : TestFixture
{
private static string LuaWithout(params string[] omitted)
{
var entries = new[]
{
"Level = \"1\"", "Title = \"t\"", "Owner = \"o\"", "Rank = \"1\"", "Score = \"2\"",
};
var kept = new System.Collections.Generic.List();
foreach (string entry in entries)
{
if (System.Array.IndexOf(omitted, entry.Substring(0, entry.IndexOf(' '))) < 0)
{
kept.Add(entry);
}
}
return "return { fields = { " + string.Join(", ", kept) + " } }";
}
public void ResumesWhereSaveLeftOff()
{
var resumed = Load(Saved(PausedTwice()));
var gates = new Gates();
gates.Open.Add("go");
resumed.Tick(gates, TestTicks.Fresh());
CheckEqual(2, resumed.Count);
CheckEqual("waited 2", resumed.Note);
CheckTrue(resumed.Finished);
}
public void CallsLocals_SurviveASaveFile()
{
var gates = new Gates();
var resumed = Load(Saved(ForeignCallSaveTests.PausedInside(gates, ticks: 2)));
gates.Open.Add("go");
resumed.Tick(gates, TestTicks.Fresh());
CheckEqual("done 7 2", resumed.Result);
CheckEqual("updated after 2", resumed.Plant.Note);
}
public void ConvertedFieldsAndLocals_SurviveASaveFile()
{
var gates = new Gates();
var original = new ConvertedScript();
original.Tick(gates, TestTicks.Fresh());
original.Destination = new Waypoint { Name = "midway", At = new Point(3, 4) };
var resumed = Load(Saved(original));
string loadedName = resumed.Destination.Name;
gates.Open.Add("go");
resumed.Tick(gates, TestTicks.Fresh());
CheckEqual("midway", loadedName);
CheckEqual(1.5, resumed.Destination.At.X);
CheckEqual(-2.0, resumed.Destination.At.Y);
}
public void ListHeldByAFieldAndALocal_IsOneListAgain()
{
var gates = new Gates();
var original = new SharingScript();
original.Route.Add(new Waypoint { Name = "start" });
original.Tick(gates, TestTicks.Fresh());
var resumed = Load(Saved(original));
gates.Open.Add("go");
resumed.Tick(gates, TestTicks.Fresh());
CheckTrue(ReferenceEquals(resumed.Route, resumed.Remembered));
CheckEqual("start", resumed.Remembered[0].Name);
}
public void NullString_ReplacesTheInitialValue()
{
var original = new CountingScript();
original.Note = null;
var loaded = Load(Saved(original));
CheckNull(loaded.Note);
}
public void ValueOfTheWrongShape_KeepsTheFieldsInitialValue()
{
CheckEqual(0, Load("return { fields = { Count = \"many\" } }").Count);
}
public void FieldWithoutAnInitializerMissingFromTheSave_Throws()
{
CheckThrow(typeof(InvalidDataException));
Load(LuaWithout("Level"));
}
public void FieldWithoutAnInitializerMissingFromTheSave_NamesTheArcAndTheField()
{
InvalidDataException thrown = null;
try
{
Load(LuaWithout("Level"));
}
catch (InvalidDataException exception)
{
thrown = exception;
}
CheckNotNull(thrown);
CheckTrue(thrown.Message.Contains("RequiredFieldsScript"));
CheckTrue(thrown.Message.Contains("'Level'"));
}
public void ReadonlyFieldMissingFromTheSave_Throws()
{
CheckThrow(typeof(InvalidDataException));
Load(LuaWithout("Owner"));
}
public void AutoPropertyWithoutAnInitializerMissingFromTheSave_Throws()
{
CheckThrow(typeof(InvalidDataException));
Load(LuaWithout("Rank"));
}
public void MembersWithInitializersMissingFromTheSave_KeepThem()
{
var loaded = Load(LuaWithout("Title", "Score"));
CheckEqual("untitled", loaded.Title);
CheckEqual(7, loaded.Score);
}
public void ScratchFieldMissingFromTheSave_IsNotRequired()
{
CheckEqual(0, Load(LuaWithout()).Spare);
}
public void FieldWithoutAnInitializerWhoseValueCannotBeRead_KeepsItsDefault()
{
var loaded = Load(
"return { fields = { Level = \"many\", Owner = \"o\", Rank = \"1\" } }");
CheckEqual(0, loaded.Level);
}
public void MalformedLua_Throws()
{
CheckThrow(typeof(InvalidDataException));
Load("return {");
}
public void LocalTheScriptLacks_Throws()
{
CheckThrow(typeof(NotImplementedException));
Load("return { locals = { [\"Run.removed\"] = \"1\" } }");
}
public void NeededLocalMissingFromTheSave_Throws()
{
CheckThrow(typeof(NotImplementedException));
Load("return { cursor = { \"wait\" } }");
}
}
}
}