diff --git a/tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Actors/DeploymentWarmThenGateTests.cs b/tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Actors/DeploymentWarmThenGateTests.cs
index 58f23c41..7028e886 100644
--- a/tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Actors/DeploymentWarmThenGateTests.cs
+++ b/tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Actors/DeploymentWarmThenGateTests.cs
@@ -248,15 +248,20 @@ public class DeploymentWarmThenGateTests : TestKit, IDisposable
"BatchTwo", ConfigJson("BatchTwo", sharedCode), "d2", "h2", true);
SiteScriptCompileCache.Clear();
- Assert.Equal(0, SiteScriptCompileCache.Hits);
+ // Baseline rather than Assert.Equal(0, Hits): Hits is a process-global counter and test
+ // classes outside this collection compile scripts in parallel, so a foreign hit can land
+ // between the Clear() and the read (deferred-work register row 91). Everything below is
+ // asserted as a delta over this baseline.
+ var hitsBefore = SiteScriptCompileCache.Hits;
CreateDeploymentManager();
AwaitAssert(() =>
{
// One compile, then repeated hits: the second pre-warm plus both PreStarts.
- Assert.True(SiteScriptCompileCache.Hits >= 3,
- $"expected the pre-warmed body to be served from cache, saw {SiteScriptCompileCache.Hits} hits");
+ Assert.True(SiteScriptCompileCache.Hits - hitsBefore >= 3,
+ $"expected the pre-warmed body to be served from cache, saw " +
+ $"{SiteScriptCompileCache.Hits - hitsBefore} hits over baseline {hitsBefore}");
}, TimeSpan.FromSeconds(20));
}
}
diff --git a/tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Scripts/SiteScriptCompileCacheTests.cs b/tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Scripts/SiteScriptCompileCacheTests.cs
index d25f7e9c..125b415b 100644
--- a/tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Scripts/SiteScriptCompileCacheTests.cs
+++ b/tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Scripts/SiteScriptCompileCacheTests.cs
@@ -7,39 +7,98 @@ namespace ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests.Scripts;
///
/// Tests for the process-wide . The cache is
/// static/process-wide state, so this class shares the "SiteScriptCompileCache" xunit
-/// collection with ScriptCompilationServiceTests (no cross-class parallelism) and
-/// calls at the top of each test.
+/// collection with ScriptCompilationServiceTests and DeploymentWarmThenGateTests
+/// (no cross-class parallelism between those three, so no concurrent
+/// ).
///
+///
+///
+/// Deferred-work register row 91. That collection does NOT stop the rest of the
+/// assembly: any test class that compiles a script — Instance/Script actor tests, deployment
+/// tests — goes through too, in parallel, and
+/// bumps the same process-global /
+/// . Absolute assertions such as
+/// Assert.Equal(1, Hits) after a Clear() therefore only held while nothing else
+/// happened to be compiling; they failed roughly 1 run in 4 of a full parallel solution run and
+/// were always green in isolation.
+///
+///
+/// The fix follows the register's row-74 pattern: assert the DELTA attributable to this test's
+/// OWN keys across its own scoped action, never an absolute global value. Two habits carry it:
+/// every test keys its cache entries on a per-test-instance unique token (),
+/// so no other class can collide with or serve them; and the global counters are only ever
+/// asserted as one-sided bounds (>= baseline + n), since foreign traffic can only add.
+/// A collection fixture spanning every script-compiling class in the assembly would fix it too,
+/// but would serialise most of the suite for the benefit of five facts.
+///
+///
[Collection("SiteScriptCompileCache")]
public class SiteScriptCompileCacheTests
{
+ ///
+ /// Slack allowed on bounds for entries inserted
+ /// by test classes outside this collection while a bound test runs (register row 91). The
+ /// exactness of the eviction claims comes from the per-key probes, not from this bound.
+ ///
+ private const int ForeignEntrySlack = 512;
+
+ /// Per-test-instance token making every cache key in this test uniquely ours.
+ private readonly string _uniq = Guid.NewGuid().ToString("N");
+
+ /// Builds a cache key body that no other test class in the assembly can produce.
+ private string Code(string body) => $"/*{_uniq}*/ {body}";
+
private static ScriptCompilationResult Ok() =>
ScriptCompilationResult.Succeeded(CSharpScript.Create