223 lines
5.9 KiB
C#
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"));
|
|
}
|
|
}
|