using System.Linq; using UnitTestSharp; namespace Ariadne.Generator.UnitTests { public class GenericScriptTests : TestFixture { public static string ProblemsOf(GeneratorRun run) { return string.Join(" | ", run.Reported.Concat(run.CompiledAt)); } public class ScriptTests : TestFixture { public void GenericScript_IsWrittenWithItsTypeParameters() { GeneratorRun run = GeneratorRun.Of(@" public partial class Counter : Arc { protected override void Run(World world) { } }"); CheckEqual("", ProblemsOf(run)); CheckTrue(run.CodeBehind.Contains("partial class Counter")); } public void LocalOfTheTypeParameter_IsKeptAcrossAPause() { GeneratorRun run = GeneratorRun.Of(@" public partial class Holder : Arc where T : class, new() { public T Kept; protected override void Run(World world) { T item = new T(); List seen = new List(); wait: while (!world.Open.Contains(""go"")) { seen.Add(item); Yield(); } Kept = item; } }"); CheckEqual("", ProblemsOf(run)); CheckTrue(run.CodeBehind.Contains("public T Run__item;")); CheckTrue(run.CodeBehind.Contains("List Run__seen;")); } public void ContextTypeUsingTheTypeParameter_Compiles() { GeneratorRun run = GeneratorRun.Of(@" public partial class Feed : Arc> { public int Seen; protected override void Run(List items) { wait: while (items.Count == 0) { Yield(); } Seen = items.Count; } }"); CheckEqual("", ProblemsOf(run)); } public void PassageWithParametersOfTheTypeParameter_Compiles() { GeneratorRun run = GeneratorRun.Of(@" public partial class Waiter : Arc where T : struct { private T Wait(World world, T start, out T last) { T current = start; wait: while (!world.Open.Contains(""go"")) { Yield(); } last = current; return current; } protected override void Run(World world) { T back; first: T got = Wait(world, default(T), out back); } }"); CheckEqual("", ProblemsOf(run)); } public void ScriptNestedInAGenericContainer_Compiles() { GeneratorRun run = GeneratorRun.Of(@" public partial class Outer { public partial class Inner : Arc { private T held; protected override void Run(World world) { T item = held; wait: while (!world.Open.Contains(""go"")) { Yield(); } held = item; } } }"); CheckEqual("", ProblemsOf(run)); CheckTrue(run.CodeBehind.Contains("partial class Outer")); } public void ScriptWithTheNameOfAGenericOfAnotherArity_Compiles() { GeneratorRun run = GeneratorRun.Of(@" public partial class Same : Arc { protected override void Run(World world) { } } public partial class Same : Arc { protected override void Run(World world) { } }"); CheckEqual("", ProblemsOf(run)); } } public class BaseClassTests : TestFixture { public void FieldsOnlyGenericBase_SavesItsFields() { GeneratorRun run = GeneratorRun.Of( "public abstract partial class Mission : Arc { public T Stage; }"); CheckEqual("", ProblemsOf(run)); CheckTrue(run.CodeBehind.Contains("writer.Field(\"Stage\", this.Stage);")); } public void ScriptDerivedFromAConstructedGenericBase_RunsTheBasesPassage() { GeneratorRun run = GeneratorRun.Of(@" public abstract partial class Steps : Arc { protected T Last; protected void Hold(World world, T value) { T held = value; hold: while (!world.Open.Contains(""go"")) { Yield(); } Last = held; } } public partial class IntSteps : Steps { protected override void Run(World world) { int local = 3; first: Hold(world, local); } }"); CheckEqual("", ProblemsOf(run)); } public void ScriptDerivedFromAGenericScript_Compiles() { GeneratorRun run = GeneratorRun.Of(@" public partial class Base : Arc { protected override void Run(World world) { T value = default(T); wait: while (!world.Open.Contains(""go"")) { Yield(); } value.ToString(); } } public partial class Derived : Base { public int Stage; }"); CheckEqual("", ProblemsOf(run)); } public void GenericScriptDerivedFromAGenericBase_Compiles() { GeneratorRun run = GeneratorRun.Of(@" public abstract partial class Steps : Arc { protected void Hold(World world, T value) { T held = value; hold: while (!world.Open.Contains(""go"")) { Yield(); } } } public partial class Stepper : Steps> { protected override void Run(World world) { List local = new List(); first: Hold(world, local); } }"); CheckEqual("", ProblemsOf(run)); } } public class ForeignCallTests : TestFixture { public void CallOnAConstructedGenericArc_Compiles() { GeneratorRun run = GeneratorRun.Of(@" public partial class Plant : Arc { public int Updates; public void Update(World world, T seed) { T kept = seed; wait: while (!world.Open.Contains(""go"")) { Yield(); } ++Updates; } protected override void Run(World world) { } } public partial class Tender : Arc { public Plant Plant; protected override void Run(World world) { string seed = ""x""; update: Plant.Update(world, seed); } }"); CheckEqual("", ProblemsOf(run)); CheckTrue(run.CodeBehind.Contains("global::Plant.__Frame")); } public void CallOnGenericArcsOfTwoInstantiations_KeepsEachFrameApart() { GeneratorRun run = GeneratorRun.Of(@" public partial class Plant : Arc { public void Update(World world, T seed) { T kept = seed; wait: while (!world.Open.Contains(""go"")) { Yield(); } } protected override void Run(World world) { } } public partial class Tender : Arc { public Plant Words; public Plant Numbers; protected override void Run(World world) { first: Words.Update(world, ""x""); second: Numbers.Update(world, 3); } }"); CheckEqual("", ProblemsOf(run)); CheckTrue(run.CodeBehind.Contains("global::Plant.__Frame")); CheckTrue(run.CodeBehind.Contains("global::Plant.__Frame")); } public void CallOnAnArcOfTheCallersOwnTypeParameter_Compiles() { GeneratorRun run = GeneratorRun.Of(@" public partial class Plant : Arc { public void Update(World world, T seed) { T kept = seed; wait: while (!world.Open.Contains(""go"")) { Yield(); } } protected override void Run(World world) { } } public partial class Tender : Arc { public Plant Plant; protected override void Run(World world) { U seed = default(U); update: Plant.Update(world, seed); } }"); CheckEqual("", ProblemsOf(run)); } } } }