67 lines
2.9 KiB
C#
67 lines
2.9 KiB
C#
using ZB.MOM.WW.ScadaBridge.ScriptAnalysis;
|
|
|
|
namespace ZB.MOM.WW.ScadaBridge.ScriptAnalysis.Tests;
|
|
|
|
/// <summary>
|
|
/// Review 2026-10-21 04/P3: <see cref="ScriptTrustValidator.FindViolations(string, IEnumerable{Microsoft.CodeAnalysis.MetadataReference})"/>
|
|
/// 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.
|
|
/// </summary>
|
|
public class ScriptTrustValidatorCacheTests
|
|
{
|
|
/// <summary>Verifies that the same violating code analysed twice is served from the cache.</summary>
|
|
[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
|
|
}
|
|
|
|
/// <summary>Verifies that a clean verdict is cached too.</summary>
|
|
[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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
[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);
|
|
}
|
|
|
|
/// <summary>Verifies that the shared verdict cannot be mutated by a caller to poison the cache.</summary>
|
|
[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<string>);
|
|
Assert.True(verdict is System.Collections.Generic.ICollection<string> { IsReadOnly: true });
|
|
}
|
|
}
|