using Microsoft.Extensions.Options; using StellaOps.AirGap.Time.Models; using StellaOps.AirGap.Time.Parsing; using StellaOps.AirGap.Time.Services; namespace StellaOps.AirGap.Time.Tests; public class TimeAnchorLoaderTests { [Fact] public void RejectsInvalidHex() { var loader = Build(); var trust = new[] { new TimeTrustRoot("k1", new byte[32], "ed25519") }; var result = loader.TryLoadHex("not-hex", TimeTokenFormat.Roughtime, trust, out _); Assert.False(result.IsValid); Assert.Equal("token-hex-invalid", result.Reason); } [Fact] public void LoadsHexToken() { var loader = Build(); var hex = "01020304"; var trust = new[] { new TimeTrustRoot("k1", new byte[32], "ed25519") }; var result = loader.TryLoadHex(hex, TimeTokenFormat.Roughtime, trust, out var anchor); Assert.True(result.IsValid); Assert.Equal("Roughtime", anchor.Format); } [Fact] public void RejectsIncompatibleTrustRoots() { var loader = Build(); var hex = "010203"; var rsaKey = new byte[128]; var trust = new[] { new TimeTrustRoot("k1", rsaKey, "rsa") }; var result = loader.TryLoadHex(hex, TimeTokenFormat.Roughtime, trust, out _); Assert.False(result.IsValid); Assert.Equal("trust-roots-incompatible-format", result.Reason); } [Fact] public void RejectsWhenTrustRootsMissing() { var loader = Build(); var result = loader.TryLoadHex("010203", TimeTokenFormat.Roughtime, Array.Empty(), out _); Assert.False(result.IsValid); Assert.Equal("trust-roots-required", result.Reason); } private static TimeAnchorLoader Build() { var options = Options.Create(new AirGapOptions { AllowUntrustedAnchors = false }); return new TimeAnchorLoader(new TimeVerificationService(), new TimeTokenParser(), options); } }