using ZB.MOM.WW.ScadaBridge.ScriptAnalysis; namespace ZB.MOM.WW.ScadaBridge.ScriptAnalysis.Tests; /// /// Review 2026-10-21 01/SR-U2: synchronously blocking on a Task inside a site /// script (.Result, .Wait(), .GetAwaiter().GetResult()) can /// starve the dedicated script-execution pool — the awaited helper's continuation /// is queued to the same pool the blocked worker occupies. The analyzer reports an /// advisory for each such use, resolved semantically so a non-Task .Result /// is not flagged. /// public class BlockingWaitAnalyzerTests { /// Verifies that each blocking-wait shape on a Task is reported. /// A script blocking on a Task. [Theory] [InlineData("var r = Instance.CallScript(\"Calc\").Result;")] [InlineData("var s = Notify.Status(\"id\").Result;")] [InlineData("Instance.CallScript(\"Calc\").Wait();")] [InlineData("var r = Instance.CallScript(\"Calc\").GetAwaiter().GetResult();")] [InlineData("var a = Alarms.CurrentAsync().Result;")] [InlineData("var t = System.Threading.Tasks.Task.Delay(1); t.Wait(100);")] [InlineData("var r = Instance.CallScript(\"Calc\").ConfigureAwait(false).GetAwaiter().GetResult();")] public void Find_ReportsBlockingWaitOnTask(string code) { Assert.NotEmpty(BlockingWaitAnalyzer.Find(code, typeof(ScriptCompileSurface))); } /// Verifies that awaited calls and non-Task members named Result/Wait are not reported. /// A script that does not block on a Task. [Theory] [InlineData("var r = await Instance.CallScript(\"Calc\");")] [InlineData("var a = await Alarms.CurrentAsync();")] [InlineData("var o = new { Result = 1 }; var x = o.Result;")] [InlineData("var t = Instance.CallScript(\"Calc\"); return t.IsCompleted;")] [InlineData("")] public void Find_IgnoresNonBlockingCode(string code) { Assert.Empty(BlockingWaitAnalyzer.Find(code, typeof(ScriptCompileSurface))); } /// Verifies that the advisory names the blocking member so the author can find it. [Fact] public void Find_MessageNamesTheMember() { var advisories = BlockingWaitAnalyzer.Find("var r = Instance.CallScript(\"Calc\").Result;", typeof(ScriptCompileSurface)); Assert.Contains(advisories, a => a.Contains(".Result") && a.Contains("await")); } }