using ZB.MOM.WW.ScadaBridge.Commons.Entities.ExternalSystems;
namespace ZB.MOM.WW.ScadaBridge.ExternalSystemGateway.Tests;
/// Tests for (review 2026-10-21 05/P2).
public class ExternalDefinitionLookupCacheTests
{
private static ExternalSystemDefinition Sys() => new("S", "https://x", "none") { Id = 1 };
/// Verifies hits within the TTL skip the repository and expiry refetches.
/// A task that represents the asynchronous operation.
[Fact]
public async Task Hit_WithinTtl_SkipsFetch_AndExpiryRefetches()
{
var time = new FakeTimeProvider(DateTimeOffset.UtcNow);
var cache = new ExternalDefinitionLookupCache(TimeSpan.FromSeconds(5), time);
var fetches = 0;
Task Fetch() { fetches++; return Task.FromResult(Sys()); }
await cache.GetSystemAsync("S", Fetch);
await cache.GetSystemAsync("S", Fetch);
Assert.Equal(1, fetches);
time.Advance(TimeSpan.FromSeconds(6));
await cache.GetSystemAsync("S", Fetch);
Assert.Equal(2, fetches);
}
/// Verifies misses are not cached and a zero TTL disables caching.
/// A task that represents the asynchronous operation.
[Fact]
public async Task NotFound_IsNotCached_AndZeroTtlDisables()
{
var cache = new ExternalDefinitionLookupCache(TimeSpan.FromSeconds(5));
var fetches = 0;
Task Miss() { fetches++; return Task.FromResult(null); }
await cache.GetSystemAsync("S", Miss);
await cache.GetSystemAsync("S", Miss);
Assert.Equal(2, fetches);
var off = new ExternalDefinitionLookupCache(TimeSpan.Zero);
fetches = 0;
Task Hit() { fetches++; return Task.FromResult(Sys()); }
await off.GetSystemAsync("S", Hit);
await off.GetSystemAsync("S", Hit);
Assert.Equal(2, fetches);
}
private sealed class FakeTimeProvider(DateTimeOffset start) : TimeProvider
{
private DateTimeOffset _now = start;
public override DateTimeOffset GetUtcNow() => _now;
public void Advance(TimeSpan by) => _now += by;
}
}