using System.Linq; using UnitTestSharp; namespace Ariadne.Generator.UnitTests { public class ForeignSpillTests : TestFixture { public const string Counter = @" public partial class Counter : Arc { public int Count(World world) { wait: while (!world.Open.Contains(""wait"")) { Yield(); } return 3; } public bool Check(World world) { wait: while (!world.Open.Contains(""wait"")) { Yield(); } return true; } protected override void Run(World world) { } } "; public class LiftTests : TestFixture { public void CallInAnExpressionStatement_PausesBeforeTheStatementRuns() { GeneratorRun run = GeneratorRun.Of(Counter + @" public partial class Mission : Arc { public Counter Plant = new Counter(); protected override void Run(World world) { first: world.Open.Add((Plant.Count(world) + 1).ToString()); } }"); CheckEqual(0, run.Reported.Count); CheckEqual(0, run.Compiled.Count); CheckTrue(run.CodeBehind.Contains("Count__Passage(")); CheckTrue(run.CodeBehind.Contains("Run____call_first_receiver")); CheckTrue(run.CodeBehind.Contains("world.Open.Add((__frame.Run____spill1 + 1).ToString());")); CheckFalse(run.CodeBehind.Contains("Plant.Count(world)")); } public void CallInADeclaration_PausesBeforeTheLocalIsSet() { GeneratorRun run = GeneratorRun.Of(Counter + @" public partial class Mission : Arc { public Counter Plant = new Counter(); protected override void Run(World world) { first: int total = Plant.Count(world) + 1; world.Open.Add(total.ToString()); } }"); CheckEqual(0, run.Reported.Count); CheckEqual(0, run.Compiled.Count); } public void CallInTheConditionOfAnIf_PausesBeforeTheTest() { GeneratorRun run = GeneratorRun.Of(Counter + @" public partial class Mission : Arc { public Counter Plant = new Counter(); protected override void Run(World world) { first: if (Plant.Check(world)) { world.Open.Add(""yes""); } } }"); CheckEqual(0, run.Reported.Count); CheckEqual(0, run.Compiled.Count); } public void CallOnTheRightOfAnAnd_OnlyRunsWhenTheLeftIsTrue() { GeneratorRun run = GeneratorRun.Of(Counter + @" public partial class Mission : Arc { public Counter Plant = new Counter(); protected override void Run(World world) { first: if (world.Open.Count == 0 && Plant.Check(world)) { world.Open.Add(""yes""); } } }"); CheckEqual(0, run.Reported.Count); CheckEqual(0, run.Compiled.Count); } public void TwoCallsOnTwoArcs_EachKeepTheirOwnReceiver() { GeneratorRun run = GeneratorRun.Of(Counter + @" public partial class Mission : Arc { public Counter Plant = new Counter(); public Counter Pump = new Counter(); protected override void Run(World world) { first: world.Open.Add((Plant.Count(world) + Pump.Count(world)).ToString()); } }"); CheckEqual(0, run.Reported.Count); CheckEqual(0, run.Compiled.Count); CheckTrue(run.CodeBehind.Contains("Run____call_first_receiver")); CheckTrue(run.CodeBehind.Contains("Run____call_first__n1_receiver")); } public void CallsThatSaveLocals_ListThemAmongTheCallersBehindTheCallsPrefix() { GeneratorRun run = GeneratorRun.Of(Counter + @" public partial class Mission : Arc { public Counter Plant = new Counter(); protected override void Run(World world) { first: world.Open.Add((Plant.Count(world) + 1).ToString()); } }"); CheckTrue(run.CodeBehind.Contains("lister.Scope(\"Run.first/\", typeof(global::Counter.__Frame));")); CheckTrue(run.CodeBehind.Contains("Counter.__Frame.ListParts(scope);")); } } public class ReportTests : TestFixture { public void VoidCallInAnExpression_IsStillReported() { GeneratorRun run = GeneratorRun.Of(@" public partial class Counter : Arc { public void Tick(World world) { wait: while (!world.Open.Contains(""wait"")) { Yield(); } } protected override void Run(World world) { } } public partial class Mission : Arc { public Counter Plant = new Counter(); protected override void Run(World world) { first: world.Open.Add(Plant.Tick(world).ToString()); } }"); CheckTrue(run.Reported.Any(each => each.StartsWith("ARI0004:", System.StringComparison.Ordinal))); } } } }