using FluentAssertions; using Microsoft.Extensions.Logging.Abstractions; using StellaOps.Policy.Determinization.Scoring; using Xunit; namespace StellaOps.Policy.Determinization.Tests; public class DecayedConfidenceCalculatorTests { private readonly DecayedConfidenceCalculator _calculator; public DecayedConfidenceCalculatorTests() { _calculator = new DecayedConfidenceCalculator(NullLogger.Instance); } [Fact] public void Calculate_ZeroAge_ReturnsBaseConfidence() { // Arrange var baseConfidence = 0.8; var ageDays = 0.0; // Act var result = _calculator.Calculate(baseConfidence, ageDays); // Assert result.Should().Be(baseConfidence); } [Fact] public void Calculate_HalfLife_ReturnsHalfConfidence() { // Arrange var baseConfidence = 1.0; var halfLifeDays = 14.0; var ageDays = 14.0; // Act var result = _calculator.Calculate(baseConfidence, ageDays, halfLifeDays); // Assert result.Should().BeApproximately(0.5, 0.01); } [Fact] public void Calculate_TwoHalfLives_ReturnsQuarterConfidence() { // Arrange var baseConfidence = 1.0; var halfLifeDays = 14.0; var ageDays = 28.0; // Act var result = _calculator.Calculate(baseConfidence, ageDays, halfLifeDays); // Assert result.Should().BeApproximately(0.25, 0.01); } [Fact] public void Calculate_VeryOld_ReturnsFloor() { // Arrange var baseConfidence = 1.0; var halfLifeDays = 14.0; var ageDays = 200.0; var floor = 0.1; // Act var result = _calculator.Calculate(baseConfidence, ageDays, halfLifeDays, floor); // Assert result.Should().Be(floor); } [Fact] public void CalculateDecayFactor_ZeroAge_ReturnsOne() { // Act var factor = _calculator.CalculateDecayFactor(0.0); // Assert factor.Should().Be(1.0); } [Fact] public void CalculateDecayFactor_HalfLife_ReturnsHalf() { // Act var factor = _calculator.CalculateDecayFactor(14.0, 14.0); // Assert factor.Should().BeApproximately(0.5, 0.01); } [Theory] [InlineData(-0.1)] [InlineData(1.1)] public void Calculate_InvalidBaseConfidence_ThrowsArgumentOutOfRange(double invalidConfidence) { // Act & Assert var act = () => _calculator.Calculate(invalidConfidence, 10.0); act.Should().Throw(); } [Fact] public void Calculate_NegativeAge_ThrowsArgumentOutOfRange() { // Act & Assert var act = () => _calculator.Calculate(0.8, -1.0); act.Should().Throw(); } }