using StellaOps.AirGap.Time.Models; using StellaOps.AirGap.Time.Services; using StellaOps.AirGap.Time.Stores; namespace StellaOps.AirGap.Time.Tests; public class TimeStatusServiceTests { [Fact] public async Task ReturnsUnknownWhenNoAnchor() { var svc = Build(out var telemetry); var status = await svc.GetStatusAsync("t1", DateTimeOffset.UnixEpoch); Assert.Equal(TimeAnchor.Unknown, status.Anchor); Assert.False(status.Staleness.IsWarning); Assert.Equal(0, telemetry.GetLatest("t1")?.AgeSeconds ?? 0); } [Fact] public async Task PersistsAnchorAndBudget() { var svc = Build(out var telemetry); var anchor = new TimeAnchor(DateTimeOffset.UnixEpoch, "source", "fmt", "fp", "digest"); var budget = new StalenessBudget(10, 20); await svc.SetAnchorAsync("t1", anchor, budget); var status = await svc.GetStatusAsync("t1", DateTimeOffset.UnixEpoch.AddSeconds(15)); Assert.Equal(anchor, status.Anchor); Assert.True(status.Staleness.IsWarning); Assert.False(status.Staleness.IsBreach); Assert.Equal(15, status.Staleness.AgeSeconds); var snap = telemetry.GetLatest("t1"); Assert.NotNull(snap); Assert.Equal(status.Staleness.AgeSeconds, snap!.AgeSeconds); Assert.True(snap.IsWarning); } private static TimeStatusService Build(out TimeTelemetry telemetry) { telemetry = new TimeTelemetry(); var options = Microsoft.Extensions.Options.Options.Create(new AirGapOptions()); return new TimeStatusService(new InMemoryTimeAnchorStore(), new StalenessCalculator(), telemetry, options); } }