Files
git.stella-ops.org/src/Scanner/__Tests/StellaOps.Scanner.Sources.Tests/Domain/SbomSourceRunTests.cs
2025-12-29 08:39:52 +02:00

223 lines
5.9 KiB
C#

using FluentAssertions;
using StellaOps.Scanner.Sources.Domain;
using Xunit;
namespace StellaOps.Scanner.Sources.Tests.Domain;
public class SbomSourceRunTests
{
[Fact]
public void Create_WithValidInputs_CreatesRunInPendingStatus()
{
// Arrange
var sourceId = Guid.NewGuid();
var correlationId = Guid.NewGuid().ToString("N");
// Act
var run = SbomSourceRun.Create(
sourceId: sourceId,
tenantId: "tenant-1",
trigger: SbomSourceRunTrigger.Manual,
correlationId: correlationId,
triggerDetails: "Triggered by user");
// Assert
run.RunId.Should().NotBeEmpty();
run.SourceId.Should().Be(sourceId);
run.TenantId.Should().Be("tenant-1");
run.Trigger.Should().Be(SbomSourceRunTrigger.Manual);
run.CorrelationId.Should().Be(correlationId);
run.TriggerDetails.Should().Be("Triggered by user");
run.Status.Should().Be(SbomSourceRunStatus.Pending);
run.ItemsDiscovered.Should().Be(0);
run.ItemsScanned.Should().Be(0);
}
[Fact]
public void Start_SetsStatusToRunning()
{
// Arrange
var run = CreateTestRun();
// Act
run.Start();
// Assert
run.Status.Should().Be(SbomSourceRunStatus.Running);
}
[Fact]
public void SetDiscoveredItems_UpdatesDiscoveryCount()
{
// Arrange
var run = CreateTestRun();
run.Start();
// Act
run.SetDiscoveredItems(10);
// Assert
run.ItemsDiscovered.Should().Be(10);
}
[Fact]
public void RecordItemSuccess_IncrementsCounts()
{
// Arrange
var run = CreateTestRun();
run.Start();
run.SetDiscoveredItems(5);
// Act
var scanJobId = Guid.NewGuid();
run.RecordItemSuccess(scanJobId);
run.RecordItemSuccess(Guid.NewGuid());
// Assert
run.ItemsScanned.Should().Be(2);
run.ItemsSucceeded.Should().Be(2);
run.ScanJobIds.Should().Contain(scanJobId);
}
[Fact]
public void RecordItemFailure_IncrementsCounts()
{
// Arrange
var run = CreateTestRun();
run.Start();
run.SetDiscoveredItems(5);
// Act
run.RecordItemFailure();
run.RecordItemFailure();
// Assert
run.ItemsScanned.Should().Be(2);
run.ItemsFailed.Should().Be(2);
run.ItemsSucceeded.Should().Be(0);
}
[Fact]
public void RecordItemSkipped_IncrementsCounts()
{
// Arrange
var run = CreateTestRun();
run.Start();
run.SetDiscoveredItems(5);
// Act
run.RecordItemSkipped();
// Assert
run.ItemsScanned.Should().Be(1);
run.ItemsSkipped.Should().Be(1);
}
[Fact]
public void Complete_SetsSuccessStatusAndDuration()
{
// Arrange
var run = CreateTestRun();
run.Start();
run.SetDiscoveredItems(3);
run.RecordItemSuccess(Guid.NewGuid());
run.RecordItemSuccess(Guid.NewGuid());
run.RecordItemSuccess(Guid.NewGuid());
// Act
run.Complete();
// Assert
run.Status.Should().Be(SbomSourceRunStatus.Succeeded);
run.CompletedAt.Should().NotBeNull();
run.DurationMs.Should().BeGreaterOrEqualTo(0);
}
[Fact]
public void Fail_SetsFailedStatusAndErrorMessage()
{
// Arrange
var run = CreateTestRun();
run.Start();
// Act
run.Fail("Connection timeout", new { retries = 3 });
// Assert
run.Status.Should().Be(SbomSourceRunStatus.Failed);
run.ErrorMessage.Should().Be("Connection timeout");
run.ErrorDetails.Should().NotBeNull();
run.CompletedAt.Should().NotBeNull();
}
[Fact]
public void Cancel_SetsCancelledStatus()
{
// Arrange
var run = CreateTestRun();
run.Start();
// Act
run.Cancel();
// Assert
run.Status.Should().Be(SbomSourceRunStatus.Cancelled);
run.CompletedAt.Should().NotBeNull();
}
[Fact]
public void MixedResults_TracksAllCountsCorrectly()
{
// Arrange
var run = CreateTestRun();
run.Start();
run.SetDiscoveredItems(10);
// Act
run.RecordItemSuccess(Guid.NewGuid()); // 1 success
run.RecordItemSuccess(Guid.NewGuid()); // 2 successes
run.RecordItemFailure(); // 1 failure
run.RecordItemSkipped(); // 1 skipped
run.RecordItemSuccess(Guid.NewGuid()); // 3 successes
run.RecordItemFailure(); // 2 failures
// Assert
run.ItemsScanned.Should().Be(6);
run.ItemsSucceeded.Should().Be(3);
run.ItemsFailed.Should().Be(2);
run.ItemsSkipped.Should().Be(1);
run.ScanJobIds.Should().HaveCount(3);
}
[Theory]
[InlineData(SbomSourceRunTrigger.Manual, "Manual trigger")]
[InlineData(SbomSourceRunTrigger.Scheduled, "Cron: 0 * * * *")]
[InlineData(SbomSourceRunTrigger.Webhook, "Harbor push event")]
[InlineData(SbomSourceRunTrigger.Push, "Registry push event")]
public void Create_WithDifferentTriggers_StoresTriggerInfo(
SbomSourceRunTrigger trigger,
string details)
{
// Arrange & Act
var run = SbomSourceRun.Create(
sourceId: Guid.NewGuid(),
tenantId: "tenant-1",
trigger: trigger,
correlationId: Guid.NewGuid().ToString("N"),
triggerDetails: details);
// Assert
run.Trigger.Should().Be(trigger);
run.TriggerDetails.Should().Be(details);
}
private static SbomSourceRun CreateTestRun()
{
return SbomSourceRun.Create(
sourceId: Guid.NewGuid(),
tenantId: "tenant-1",
trigger: SbomSourceRunTrigger.Manual,
correlationId: Guid.NewGuid().ToString("N"));
}
}