using ZB.MOM.WW.Secrets.Abstractions; using ZB.MOM.WW.Secrets.Replicator.AkkaDotNet.DependencyInjection; namespace ZB.MOM.WW.Secrets.Replicator.AkkaDotNet.Tests.DependencyInjection; /// /// The deferred invalidator exists to break the scadaproj#1 dependency cycle, which makes it a /// pass-through that could silently pass nothing through — the exact failure mode (inert seam, /// green suite) this library has shipped before. These tests pin the two halves of its contract: /// nothing resolves before the first eviction, and evictions actually reach the real invalidator. /// public sealed class DeferredSecretCacheInvalidatorTests { private sealed class RecordingInvalidator : ISecretCacheInvalidator { public List Evicted { get; } = []; public void Invalidate(SecretName name) => Evicted.Add(name); } [Fact] public void Construction_does_not_resolve_the_inner_invalidator() { // THE point of the type: resolving eagerly is what closed the singleton cycle and hung // every hosted process at startup. bool resolved = false; _ = new DeferredSecretCacheInvalidator(() => { resolved = true; return null; }); Assert.False(resolved); } [Fact] public void Invalidate_forwards_to_the_resolved_invalidator() { var inner = new RecordingInvalidator(); var deferred = new DeferredSecretCacheInvalidator(() => inner); var name = new SecretName("gate/alpha"); deferred.Invalidate(name); Assert.Equal([name], inner.Evicted); } [Fact] public void The_lookup_runs_once_and_the_instance_is_reused() { int lookups = 0; var inner = new RecordingInvalidator(); var deferred = new DeferredSecretCacheInvalidator(() => { lookups++; return inner; }); deferred.Invalidate(new SecretName("gate/alpha")); deferred.Invalidate(new SecretName("gate/beta")); Assert.Equal(1, lookups); Assert.Equal(2, inner.Evicted.Count); } [Fact] public void A_null_resolution_means_evictions_are_no_ops() { // Mirrors the reconciler's own contract: no invalidator registered, nothing to evict. var deferred = new DeferredSecretCacheInvalidator(() => null); deferred.Invalidate(new SecretName("gate/alpha")); } }