using ZB.MOM.WW.ScadaBridge.ScriptAnalysis;
namespace ZB.MOM.WW.ScadaBridge.ScriptAnalysis.Tests;
///
/// Review 2026-10-21 04/P3:
/// is memoised by code hash for the default (policy) reference set, so the bundle
/// importer's preview and apply passes — which call it with no change at their call
/// sites — do not redo a full-framework semantic analysis per script. A cache hit
/// returns the very same verdict instance, which is what these tests observe.
///
public class ScriptTrustValidatorCacheTests
{
/// Verifies that the same violating code analysed twice is served from the cache.
[Fact]
public void FindViolations_SameCodeTwice_SecondCallIsCacheHit()
{
var code = $"var x = System.IO.File.Exists(\"{Guid.NewGuid()}\");";
var first = ScriptTrustValidator.FindViolations(code);
var second = ScriptTrustValidator.FindViolations(code);
Assert.NotEmpty(second);
Assert.Same(first, second); // pre-fix: a fresh list per call
}
/// Verifies that a clean verdict is cached too.
[Fact]
public void FindViolations_CleanCodeTwice_SecondCallIsCacheHit()
{
var code = $"var x = \"{Guid.NewGuid()}\".Length;";
var first = ScriptTrustValidator.FindViolations(code);
var second = ScriptTrustValidator.FindViolations(code);
Assert.Empty(second);
Assert.Same(first, second);
}
///
/// Verifies that a call with extra references is never served from (or stored in)
/// the cache — extra references can change symbol resolution, so the verdict is a
/// pure function of the code only for the default reference set.
///
[Fact]
public void FindViolations_WithExtraReferences_BypassesCache()
{
var code = $"var x = System.IO.File.Exists(\"{Guid.NewGuid()}\");";
var extra = new[] { Microsoft.CodeAnalysis.MetadataReference.CreateFromFile(typeof(ScriptCompileSurface).Assembly.Location) };
var a = ScriptTrustValidator.FindViolations(code, extra);
var b = ScriptTrustValidator.FindViolations(code, extra);
var cached = ScriptTrustValidator.FindViolations(code);
Assert.NotSame(a, b);
Assert.NotSame(a, cached);
Assert.NotSame(b, cached);
}
/// Verifies that the shared verdict cannot be mutated by a caller to poison the cache.
[Fact]
public void FindViolations_ReturnedList_IsReadOnly()
{
var code = $"var x = System.IO.File.Exists(\"{Guid.NewGuid()}\");";
var verdict = ScriptTrustValidator.FindViolations(code);
Assert.False(verdict is List);
Assert.True(verdict is System.Collections.Generic.ICollection { IsReadOnly: true });
}
}