audit work, fixed StellaOps.sln warnings/errors, fixed tests, sprints work, new advisories
This commit is contained in:
@@ -0,0 +1,211 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// EpssSignalAttacherTests.cs
|
||||
// Sprint: SPRINT_20260106_001_004_BE_determinization_integration
|
||||
// Task: DBI-018 - Write unit tests for EpssSignalAttacher
|
||||
// Description: Unit tests for EPSS signal attacher
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Time.Testing;
|
||||
using Moq;
|
||||
using StellaOps.Feedser.Core.Signals;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Feedser.Core.Tests.Signals;
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
public sealed class EpssSignalAttacherTests
|
||||
{
|
||||
private readonly FakeTimeProvider _timeProvider = new();
|
||||
private readonly Mock<IEpssDataSource> _dataSourceMock = new();
|
||||
private readonly Mock<ISignalEventEmitter> _emitterMock = new();
|
||||
private readonly EpssSignalAttacher _attacher;
|
||||
|
||||
public EpssSignalAttacherTests()
|
||||
{
|
||||
_timeProvider.SetUtcNow(new DateTimeOffset(2026, 1, 7, 12, 0, 0, TimeSpan.Zero));
|
||||
|
||||
_attacher = new EpssSignalAttacher(
|
||||
_dataSourceMock.Object,
|
||||
_emitterMock.Object,
|
||||
_timeProvider,
|
||||
NullLogger<EpssSignalAttacher>.Instance);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SignalType_ReturnsEpss()
|
||||
{
|
||||
Assert.Equal("epss", _attacher.SignalType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AttachAsync_WhenDataFound_ReturnsAvailableState()
|
||||
{
|
||||
// Arrange
|
||||
var cveId = "CVE-2024-1234";
|
||||
var input = new EpssLookupInput { CveId = cveId };
|
||||
var epssData = new EpssData
|
||||
{
|
||||
CveId = cveId,
|
||||
Score = 0.85,
|
||||
Percentile = 99.2,
|
||||
ScoreDate = new DateOnly(2026, 1, 6),
|
||||
ModelVersion = "2024.10"
|
||||
};
|
||||
|
||||
_dataSourceMock
|
||||
.Setup(x => x.GetEpssAsync(cveId, null, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(epssData);
|
||||
|
||||
// Act
|
||||
var result = await _attacher.AttachAsync(input);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(SignalStatus.Available, result.Status);
|
||||
Assert.NotNull(result.Value);
|
||||
Assert.Equal(cveId, result.Value.CveId);
|
||||
Assert.Equal(0.85, result.Value.Score);
|
||||
Assert.Equal(99.2, result.Value.Percentile);
|
||||
Assert.Equal("epss-feed", result.Source);
|
||||
Assert.NotNull(result.Ttl);
|
||||
Assert.Equal(TimeSpan.FromHours(24), result.Ttl);
|
||||
|
||||
_emitterMock.Verify(x => x.EmitAsync(
|
||||
It.Is<SignalUpdatedEvent>(e =>
|
||||
e.SignalType == "epss" &&
|
||||
e.CveId == cveId &&
|
||||
e.Status == SignalStatus.Available),
|
||||
It.IsAny<CancellationToken>()),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AttachAsync_WhenDataNotFound_ReturnsNotFoundState()
|
||||
{
|
||||
// Arrange
|
||||
var cveId = "CVE-2099-9999";
|
||||
var input = new EpssLookupInput { CveId = cveId };
|
||||
|
||||
_dataSourceMock
|
||||
.Setup(x => x.GetEpssAsync(cveId, null, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync((EpssData?)null);
|
||||
|
||||
// Act
|
||||
var result = await _attacher.AttachAsync(input);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(SignalStatus.NotFound, result.Status);
|
||||
Assert.Null(result.Value);
|
||||
Assert.Equal("epss-feed", result.Source);
|
||||
|
||||
_emitterMock.Verify(x => x.EmitAsync(
|
||||
It.Is<SignalUpdatedEvent>(e =>
|
||||
e.SignalType == "epss" &&
|
||||
e.Status == SignalStatus.NotFound),
|
||||
It.IsAny<CancellationToken>()),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AttachAsync_WhenDataSourceThrows_ReturnsFailedState()
|
||||
{
|
||||
// Arrange
|
||||
var cveId = "CVE-2024-1234";
|
||||
var input = new EpssLookupInput { CveId = cveId };
|
||||
|
||||
_dataSourceMock
|
||||
.Setup(x => x.GetEpssAsync(cveId, null, It.IsAny<CancellationToken>()))
|
||||
.ThrowsAsync(new InvalidOperationException("Network error"));
|
||||
|
||||
// Act
|
||||
var result = await _attacher.AttachAsync(input);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(SignalStatus.Failed, result.Status);
|
||||
Assert.Null(result.Value);
|
||||
Assert.Equal("Network error", result.Error);
|
||||
Assert.Equal("epss-feed", result.Source);
|
||||
|
||||
_emitterMock.Verify(x => x.EmitAsync(
|
||||
It.Is<SignalUpdatedEvent>(e =>
|
||||
e.SignalType == "epss" &&
|
||||
e.Status == SignalStatus.Failed),
|
||||
It.IsAny<CancellationToken>()),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AttachAsync_WithAsOfDate_PassesDateToDataSource()
|
||||
{
|
||||
// Arrange
|
||||
var cveId = "CVE-2024-1234";
|
||||
var asOfDate = new DateOnly(2025, 12, 15);
|
||||
var input = new EpssLookupInput { CveId = cveId, AsOfDate = asOfDate };
|
||||
|
||||
_dataSourceMock
|
||||
.Setup(x => x.GetEpssAsync(cveId, asOfDate, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new EpssData
|
||||
{
|
||||
CveId = cveId,
|
||||
Score = 0.5,
|
||||
Percentile = 75.0,
|
||||
ScoreDate = asOfDate
|
||||
});
|
||||
|
||||
// Act
|
||||
var result = await _attacher.AttachAsync(input);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(SignalStatus.Available, result.Status);
|
||||
Assert.Equal(asOfDate, result.Value!.ScoreDate);
|
||||
|
||||
_dataSourceMock.Verify(x => x.GetEpssAsync(cveId, asOfDate, It.IsAny<CancellationToken>()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AttachBatchAsync_ProcessesAllInputs()
|
||||
{
|
||||
// Arrange
|
||||
var inputs = new List<EpssLookupInput>
|
||||
{
|
||||
new() { CveId = "CVE-2024-0001" },
|
||||
new() { CveId = "CVE-2024-0002" },
|
||||
new() { CveId = "CVE-2024-0003" }
|
||||
};
|
||||
|
||||
_dataSourceMock
|
||||
.Setup(x => x.GetEpssAsync(It.IsAny<string>(), null, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync((string cve, DateOnly? _, CancellationToken _) => new EpssData
|
||||
{
|
||||
CveId = cve,
|
||||
Score = 0.5,
|
||||
Percentile = 50.0,
|
||||
ScoreDate = new DateOnly(2026, 1, 6)
|
||||
});
|
||||
|
||||
// Act
|
||||
var results = await _attacher.AttachBatchAsync(inputs);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(3, results.Count);
|
||||
Assert.All(results, r => Assert.Equal(SignalStatus.Available, r.Status));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AttachAsync_CapturedAtUsesTimeProvider()
|
||||
{
|
||||
// Arrange
|
||||
var expectedTime = new DateTimeOffset(2026, 1, 7, 12, 0, 0, TimeSpan.Zero);
|
||||
var input = new EpssLookupInput { CveId = "CVE-2024-1234" };
|
||||
|
||||
_dataSourceMock
|
||||
.Setup(x => x.GetEpssAsync(It.IsAny<string>(), null, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync((EpssData?)null);
|
||||
|
||||
// Act
|
||||
var result = await _attacher.AttachAsync(input);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedTime, result.CapturedAt);
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentAssertions" />
|
||||
<PackageReference Include="Moq" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user