Files
git.stella-ops.org/src/BinaryIndex/__Tests/StellaOps.BinaryIndex.Cache.Tests/ResolutionCacheServiceTests.cs
StellaOps Bot 83c37243e0 save progress
2026-01-03 11:02:24 +02:00

104 lines
3.4 KiB
C#

using System.Text.Json;
using FluentAssertions;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Moq;
using StackExchange.Redis;
using StellaOps.BinaryIndex.Contracts.Resolution;
namespace StellaOps.BinaryIndex.Cache.Tests;
public sealed class ResolutionCacheServiceTests
{
[Fact]
public async Task GetAsync_ExpiresEarly_WhenRandomBelowThreshold()
{
var options = new ResolutionCacheOptions
{
EnableEarlyExpiry = true,
EarlyExpiryFactor = 1.0
};
var cached = new CachedResolution
{
Status = ResolutionStatus.Fixed,
CachedAt = new DateTimeOffset(2025, 1, 1, 0, 0, 0, TimeSpan.Zero),
Confidence = 1.0m
};
var payload = JsonSerializer.Serialize(
cached,
new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
var db = new Mock<IDatabase>();
db.Setup(d => d.StringGetAsync(It.IsAny<RedisKey>(), It.IsAny<CommandFlags>()))
.ReturnsAsync(payload);
db.Setup(d => d.KeyTimeToLiveAsync(It.IsAny<RedisKey>(), It.IsAny<CommandFlags>()))
.ReturnsAsync(TimeSpan.FromHours(1));
var mux = new Mock<IConnectionMultiplexer>();
mux.Setup(m => m.GetDatabase(It.IsAny<int>(), It.IsAny<object>()))
.Returns(db.Object);
var service = new ResolutionCacheService(
mux.Object,
Options.Create(options),
NullLogger<ResolutionCacheService>.Instance,
new FixedRandomSource(0.1));
var result = await service.GetAsync("resolution:key", CancellationToken.None);
result.Should().BeNull();
}
[Fact]
public async Task GetAsync_ReturnsCachedEntry_WhenRandomAboveThreshold()
{
var options = new ResolutionCacheOptions
{
EnableEarlyExpiry = true,
EarlyExpiryFactor = 1.0
};
var cached = new CachedResolution
{
Status = ResolutionStatus.Vulnerable,
CachedAt = new DateTimeOffset(2025, 1, 1, 0, 0, 0, TimeSpan.Zero),
Confidence = 0.5m
};
var payload = JsonSerializer.Serialize(
cached,
new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
var db = new Mock<IDatabase>();
db.Setup(d => d.StringGetAsync(It.IsAny<RedisKey>(), It.IsAny<CommandFlags>()))
.ReturnsAsync(payload);
db.Setup(d => d.KeyTimeToLiveAsync(It.IsAny<RedisKey>(), It.IsAny<CommandFlags>()))
.ReturnsAsync(TimeSpan.FromHours(1));
var mux = new Mock<IConnectionMultiplexer>();
mux.Setup(m => m.GetDatabase(It.IsAny<int>(), It.IsAny<object>()))
.Returns(db.Object);
var service = new ResolutionCacheService(
mux.Object,
Options.Create(options),
NullLogger<ResolutionCacheService>.Instance,
new FixedRandomSource(0.9));
var result = await service.GetAsync("resolution:key", CancellationToken.None);
result.Should().NotBeNull();
result!.Status.Should().Be(ResolutionStatus.Vulnerable);
}
private sealed class FixedRandomSource : IRandomSource
{
private readonly double _value;
public FixedRandomSource(double value)
{
_value = value;
}
public double NextDouble() => _value;
}
}