docs(tests): fix CommentChecker findings across tests/ — 13,392 → 0 (repo-wide scan clean)

Comment/XML-doc changes only:
- add summaries to ~10k test methods, fixtures, fakes and helpers
  (+ <param> on theories, <returns> on async Task methods,
  <inheritdoc/> on interface implementations the checker can resolve)
- strip ~2.6k project-tracking references (WP*, P*-*, row-NN, Task N,
  #NN, Component-0NN) from comments, keeping the explanatory text;
  reword false positives in comments only
- real docs on fakes implementing BCL/library interfaces
  (IDisposable, ILogger, IOptionsMonitor, IAsyncLifetime)
- reword the last 5 src/ false positives (CWE-1236, failures-1,
  year-0001, M365)

Only non-comment edits: four one-line nested classes split across lines
so members can carry docs. Build 0 errors / 0 warnings.
This commit is contained in:
Joseph Doherty
2026-10-07 15:05:49 -04:00
parent 0ffd4bdbea
commit 513fa1aa16
998 changed files with 17896 additions and 2395 deletions
@@ -15,10 +15,8 @@ using ZB.MOM.WW.ScadaBridge.SiteRuntime.Scripts;
namespace ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests.Actors;
/// <summary>
/// WP-15: Script Actor and Script Execution Actor tests.
/// WP-20: Recursion limit tests.
/// WP-22: Tell vs Ask convention tests.
/// WP-32: Script error handling tests.
/// Script Actor and Script Execution Actor tests, including recursion limit,
/// Tell vs Ask convention and script error handling coverage.
/// </summary>
public class ScriptActorTests : TestKit, IDisposable
{
@@ -26,7 +24,7 @@ public class ScriptActorTests : TestKit, IDisposable
private readonly SiteRuntimeOptions _options;
private readonly ScriptCompilationService _compilationService;
// Gitea #16/#18: every ScriptActor built here runs its trigger-expression
// Every ScriptActor built here runs its trigger-expression
// evaluation and spawned script bodies on THIS class's own scheduler, never the
// process-wide singleton. That is what makes the faulted-task test below
// un-leakable across the assembly: any worker a test strands (or the 30 s bounded
@@ -34,6 +32,7 @@ public class ScriptActorTests : TestKit, IDisposable
// teardown, so it can never starve unrelated test classes' script executions.
private readonly ScriptExecutionScheduler _scheduler;
/// <summary>Initializes the test with an isolated script scheduler, shared script library and compilation service.</summary>
public ScriptActorTests()
{
_compilationService = new ScriptCompilationService(
@@ -48,6 +47,7 @@ public class ScriptActorTests : TestKit, IDisposable
_scheduler = new ScriptExecutionScheduler(_options.ScriptExecutionThreadCount);
}
/// <inheritdoc />
void IDisposable.Dispose()
{
Shutdown();
@@ -65,6 +65,7 @@ public class ScriptActorTests : TestKit, IDisposable
return script;
}
/// <summary>Verifies that calling a script returns its result.</summary>
[Fact]
public void ScriptActor_CallScript_ReturnsResult()
{
@@ -91,7 +92,7 @@ public class ScriptActorTests : TestKit, IDisposable
null, // serviceProvider
_scheduler)));
// Ask pattern (WP-22) for CallScript
// Ask pattern for CallScript
scriptActor.Tell(new ScriptCallRequest("GetAnswer", null, 0, "corr-1"));
var result = ExpectMsg<ScriptCallResult>(TimeSpan.FromSeconds(10));
@@ -99,6 +100,7 @@ public class ScriptActorTests : TestKit, IDisposable
Assert.Equal(42, result.ReturnValue);
}
/// <summary>Verifies that calling a script with parameters passes them to the script.</summary>
[Fact]
public void ScriptActor_CallScript_WithParameters_Works()
{
@@ -133,6 +135,7 @@ public class ScriptActorTests : TestKit, IDisposable
Assert.Equal(7, result.ReturnValue);
}
/// <summary>Verifies that a script actor with no compiled script replies with an error.</summary>
[Fact]
public void ScriptActor_NullCompiledScript_ReturnsError()
{
@@ -165,6 +168,7 @@ public class ScriptActorTests : TestKit, IDisposable
Assert.Contains("not compiled", result.ErrorMessage);
}
/// <summary>Verifies that a value-change trigger spawns a script execution.</summary>
[Fact]
public void ScriptActor_ValueChangeTrigger_SpawnsExecution()
{
@@ -202,6 +206,7 @@ public class ScriptActorTests : TestKit, IDisposable
ExpectNoMsg(TimeSpan.FromSeconds(1));
}
/// <summary>Verifies that a trigger arriving within the minimum time between runs is skipped.</summary>
[Fact]
public void ScriptActor_MinTimeBetweenRuns_SkipsIfTooSoon()
{
@@ -243,6 +248,7 @@ public class ScriptActorTests : TestKit, IDisposable
ExpectNoMsg(TimeSpan.FromSeconds(1));
}
/// <summary>Verifies that a script failure does not disable the script actor.</summary>
[Fact]
public void ScriptActor_WP32_ScriptFailure_DoesNotDisable()
{
@@ -342,6 +348,7 @@ public class ScriptActorTests : TestKit, IDisposable
private AttributeValueChanged Change(string attribute, object? value) =>
new("TestInstance", attribute, attribute, value, "Good", DateTimeOffset.UtcNow);
/// <summary>Verifies that the non-numeric fallback comparison of a conditional trigger is culture-invariant.</summary>
[Fact]
public void ConditionalTrigger_NonNumericFallback_IsCultureInvariant()
{
@@ -393,6 +400,7 @@ public class ScriptActorTests : TestKit, IDisposable
return s;
}
/// <summary>Verifies that a faulted expression evaluation clears the in-flight flag and drains the pending evaluation.</summary>
[Fact]
public void ExpressionEvalTaskFault_ClearsInFlight_AndDrainsPendingEvaluation()
{
@@ -406,10 +414,10 @@ public class ScriptActorTests : TestKit, IDisposable
actor.Tell(Change("A", "1")); // eval starts off-thread and BLOCKS → _evalInFlight = true
AwaitAssert(() => Assert.Equal(1, EvalGate.Entries), TimeSpan.FromSeconds(10));
// WP3.1: the blocked evaluation no longer occupies a script-execution worker at
// The blocked evaluation no longer occupies a script-execution worker at
// all — it runs on the shared thread pool behind TriggerEvalGate, which is the
// whole point of finding #4. The blocking pool must be completely idle here; the
// pre-WP3.1 assertion was the opposite (BusyThreadCount == 1).
// whole point of moving it off the blocking pool. The blocking pool must be completely idle here; the
// earlier assertion was the opposite (BusyThreadCount == 1).
Assert.Equal(0, _scheduler.BusyThreadCount);
Assert.Equal(0, _scheduler.QueueDepth);
@@ -433,14 +441,15 @@ public class ScriptActorTests : TestKit, IDisposable
}
}
/// <summary>Verifies that an expression trigger is evaluated off the blocking script pool and still fires.</summary>
[Fact]
public void ExpressionTrigger_EvaluatesOffTheBlockingScriptPool_AndStillFires()
{
// WP3.1 retarget of the former P1 assertion, whose sense is deliberately INVERTED.
// Retarget of the former P1 assertion, whose sense is deliberately INVERTED.
//
// P1 moved trigger-expression evaluation off the actor's dispatcher thread and onto
// the dedicated script-execution scheduler, and this test asserted exactly that
// ("evaluated on a script-execution-* thread"). WP3.1 (finding #4) proved that
// ("evaluated on a script-execution-* thread"). Later work proved that
// destination wrong: sharing the blocking pool meant N blocked script bodies stalled
// every Expression trigger on the node indefinitely. Evaluations are non-blocking by
// construction, so they now run as plain async work on the shared .NET thread pool
@@ -463,6 +472,7 @@ public class ScriptActorTests : TestKit, IDisposable
instance.ExpectMsg<SetStaticAttributeCommand>(TimeSpan.FromSeconds(10)); // fired ⇒ evaluated off the blocking pool
}
/// <summary>Verifies that a while-true conditional trigger fires on the edge and then re-fires while the condition holds.</summary>
[Fact]
public void ScriptActor_ConditionalWhileTrue_FiresOnEdgeThenReFiresWhileConditionHolds()
{
@@ -482,6 +492,7 @@ public class ScriptActorTests : TestKit, IDisposable
instance.ExpectMsg<SetStaticAttributeCommand>(TimeSpan.FromSeconds(2)); // tick 2
}
/// <summary>Verifies that a while-true conditional trigger stops re-firing when the condition goes false.</summary>
[Fact]
public void ScriptActor_ConditionalWhileTrue_StopsReFiringWhenConditionGoesFalse()
{
@@ -501,6 +512,7 @@ public class ScriptActorTests : TestKit, IDisposable
instance.ExpectNoMsg(TimeSpan.FromMilliseconds(700)); // re-firing has stopped
}
/// <summary>Verifies that a while-true conditional trigger re-arms after the condition goes false and then true again.</summary>
[Fact]
public void ScriptActor_ConditionalWhileTrue_ReArmsAfterConditionFalseThenTrueAgain()
{
@@ -520,6 +532,7 @@ public class ScriptActorTests : TestKit, IDisposable
instance.ExpectMsg<SetStaticAttributeCommand>(TimeSpan.FromSeconds(2));
}
/// <summary>Verifies that a while-true conditional trigger without a minimum time between runs fires only once.</summary>
[Fact]
public void ScriptActor_ConditionalWhileTrue_WithoutMinTimeBetweenRuns_FiresOnceOnly()
{
@@ -535,6 +548,7 @@ public class ScriptActorTests : TestKit, IDisposable
instance.ExpectNoMsg(TimeSpan.FromMilliseconds(900)); // no repeats
}
/// <summary>Verifies that an on-true conditional trigger fires on each change while true, without a timer.</summary>
[Fact]
public void ScriptActor_ConditionalOnTrue_FiresOnEachChangeWhileTrue_NoTimer()
{
@@ -554,6 +568,7 @@ public class ScriptActorTests : TestKit, IDisposable
instance.ExpectNoMsg(TimeSpan.FromMilliseconds(600)); // no self-driven re-fire
}
/// <summary>Verifies that a while-true expression trigger re-fires while the expression holds.</summary>
[Fact]
public void ScriptActor_ExpressionWhileTrue_ReFiresWhileExpressionHolds()
{
@@ -574,6 +589,7 @@ public class ScriptActorTests : TestKit, IDisposable
instance.ExpectNoMsg(TimeSpan.FromMilliseconds(500));
}
/// <summary>Verifies that an on-true expression trigger fires once per false-to-true edge.</summary>
[Fact]
public void ScriptActor_ExpressionOnTrue_FiresOncePerFalseToTrueEdge()
{
@@ -618,7 +634,7 @@ public static class EvalGate
/// Resets the gate to a fresh, permit-free state and zeroes the entry counter.
/// Called at the start of the test so counts never carry across runs — the old
/// static leaked <c>_entries</c> from whatever compiled an expression before it
/// (Gitea #16).
/// .
/// </summary>
public static void Reset()
{
@@ -630,9 +646,10 @@ public static class EvalGate
/// Counts the entry, then blocks the calling script-scheduler thread until a permit
/// is released. The wait is BOUNDED (30 s): even if a test releases too few permits,
/// a stranded evaluation frees its worker instead of parking it for the rest of the
/// process — the leak mechanism behind Gitea #16. Returns false so a trigger
/// process — the leak mechanism behind stranded workers. Returns false so a trigger
/// expression built on it evaluates to "not fired".
/// </summary>
/// <returns>Always <see langword="false"/>.</returns>
public static bool Block()
{
Interlocked.Increment(ref _entries);