using Fleet.Core; namespace Fleet.Tests; public sealed class CoreTests { [Theory] [InlineData(0UL)] [InlineData(1UL)] [InlineData(127UL)] [InlineData(128UL)] [InlineData(300UL)] [InlineData(ulong.MaxValue)] public void VarInt_RoundTrips(ulong value) { Span buffer = stackalloc byte[VarInt.MaxBytes]; int written = VarInt.Write(buffer, value); Assert.True(VarInt.TryRead(buffer[..written], out ulong read, out int consumed)); Assert.Equal(value, read); Assert.Equal(written, consumed); } [Fact] public void VarInt_RejectsTruncatedAndOverlongInput() { Assert.False(VarInt.TryRead([0x80], out _, out _)); Assert.False(VarInt.TryRead([], out _, out _)); byte[] overlong = [.. Enumerable.Repeat((byte)0x80, 11), 0x01]; Assert.False(VarInt.TryRead(overlong, out _, out _)); } [Theory] [InlineData(0L)] [InlineData(-1L)] [InlineData(1L)] [InlineData(long.MinValue)] [InlineData(long.MaxValue)] public void ZigZag_RoundTrips_AndKeepsSmallMagnitudesSmall(long value) { Assert.Equal(value, VarInt.UnZigZag(VarInt.ZigZag(value))); if (value is >= -63 and <= 63) { Assert.True(VarInt.ZigZag(value) < 128); } } [Fact] public void Ulid_IsTwentySixCharacters_SortsByTime_AndDoesNotRepeat() { var time = new FakeClock(new DateTimeOffset(2026, 1, 1, 0, 0, 0, TimeSpan.Zero)); string a = Ulid.New(time); time.Advance(TimeSpan.FromMilliseconds(5)); string b = Ulid.New(time); Assert.Equal(26, a.Length); Assert.True(string.CompareOrdinal(a, b) < 0); Assert.Equal(1000, Enumerable.Range(0, 1000).Select(_ => Ulid.New(time)).Distinct().Count()); Assert.StartsWith("agt_", Ulid.NewPrefixed("agt", time)); } [Fact] public void Tokens_AreHighEntropy_AndOnlyTheHashIsComparable() { string a = TokenHash.NewToken("jt"); string b = TokenHash.NewToken("jt"); Assert.NotEqual(a, b); Assert.StartsWith("jt_", a); Assert.Equal(3 + 43, a.Length); Assert.True(TokenHash.FixedTimeEquals(TokenHash.Sha256(a), TokenHash.Sha256(a))); Assert.False(TokenHash.FixedTimeEquals(TokenHash.Sha256(a), TokenHash.Sha256(b))); } [Fact] public void Base64Url_RoundTrips_AndRejectsGarbage() { byte[] data = [0xFB, 0xFF, 0xFE, 0x00, 0x01]; string text = Base64Url.Encode(data); Assert.DoesNotContain('+', text); Assert.DoesNotContain('/', text); Assert.DoesNotContain('=', text); Assert.True(Base64Url.TryDecode(text, out byte[] back)); Assert.Equal(data, back); Assert.False(Base64Url.TryDecode("***", out _)); } [Fact] public void Result_CarriesEitherAValueOrAnError_AndRefusesTheWrongAccess() { Result ok = Result.Ok(5); Result failed = Result.Fail(FleetErrors.NotFound, "missing"); Assert.True(ok.IsSuccess); Assert.Equal(10, ok.Map(v => v * 2).Value); Assert.False(failed.IsSuccess); Assert.Equal(FleetErrors.NotFound, failed.Error.Code); Assert.Throws(() => failed.Value); Assert.Throws(() => ok.Error); Assert.Equal("fleet_not_found", failed.Map(v => v).Error.Code.Value); } [Fact] public void FrameworkErrorCodes_ArePrefixedAndSnakeCase() { foreach (System.Reflection.FieldInfo field in typeof(FleetErrors).GetFields()) { string value = ((ErrorCode)field.GetValue(null)!).Value; Assert.StartsWith("fleet_", value); Assert.Matches("^[a-z]+(_[a-z]+)*$", value); } } private sealed class FakeClock : TimeProvider { private DateTimeOffset _now; public FakeClock(DateTimeOffset now) { _now = now; } public override DateTimeOffset GetUtcNow() => _now; public void Advance(TimeSpan by) => _now += by; } }