up
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled

This commit is contained in:
StellaOps Bot
2025-11-28 09:40:40 +02:00
parent 1c6730a1d2
commit 05da719048
206 changed files with 34741 additions and 1751 deletions

View File

@@ -0,0 +1,268 @@
using System.Collections.Immutable;
using FluentAssertions;
using StellaOps.Policy.Engine.Materialization;
using Xunit;
namespace StellaOps.Policy.Engine.Tests.Materialization;
public sealed class MaterializationTests
{
#region EffectiveFinding.CreateId Tests
[Fact]
public void CreateId_IsDeterministic()
{
var id1 = EffectiveFinding.CreateId("tenant1", "policy-1", "pkg:npm/lodash@4.17.21", "CVE-2021-12345");
var id2 = EffectiveFinding.CreateId("tenant1", "policy-1", "pkg:npm/lodash@4.17.21", "CVE-2021-12345");
id1.Should().Be(id2);
id1.Should().StartWith("sha256:");
}
[Fact]
public void CreateId_NormalizesTenant()
{
var id1 = EffectiveFinding.CreateId("TENANT1", "policy-1", "pkg:npm/lodash", "CVE-2021-12345");
var id2 = EffectiveFinding.CreateId("tenant1", "policy-1", "pkg:npm/lodash", "CVE-2021-12345");
id1.Should().Be(id2);
}
[Fact]
public void CreateId_NormalizesPurl()
{
var id1 = EffectiveFinding.CreateId("tenant1", "policy-1", "PKG:NPM/LODASH", "CVE-2021-12345");
var id2 = EffectiveFinding.CreateId("tenant1", "policy-1", "pkg:npm/lodash", "CVE-2021-12345");
id1.Should().Be(id2);
}
[Fact]
public void CreateId_DiffersForDifferentInput()
{
var id1 = EffectiveFinding.CreateId("tenant1", "policy-1", "pkg:npm/lodash", "CVE-2021-12345");
var id2 = EffectiveFinding.CreateId("tenant1", "policy-1", "pkg:npm/lodash", "CVE-2021-99999");
id1.Should().NotBe(id2);
}
[Fact]
public void CreateId_HandlesNullValues()
{
var id = EffectiveFinding.CreateId(null!, "policy", "purl", "advisory");
id.Should().StartWith("sha256:");
}
#endregion
#region EffectiveFinding.ComputeContentHash Tests
[Fact]
public void ComputeContentHash_IsDeterministic()
{
var hash1 = EffectiveFinding.ComputeContentHash("affected", "High", "severity-rule", "not_affected", null);
var hash2 = EffectiveFinding.ComputeContentHash("affected", "High", "severity-rule", "not_affected", null);
hash1.Should().Be(hash2);
}
[Fact]
public void ComputeContentHash_DiffersForDifferentStatus()
{
var hash1 = EffectiveFinding.ComputeContentHash("affected", "High", null, null, null);
var hash2 = EffectiveFinding.ComputeContentHash("suppressed", "High", null, null, null);
hash1.Should().NotBe(hash2);
}
[Fact]
public void ComputeContentHash_DiffersForDifferentSeverity()
{
var hash1 = EffectiveFinding.ComputeContentHash("affected", "High", null, null, null);
var hash2 = EffectiveFinding.ComputeContentHash("affected", "Critical", null, null, null);
hash1.Should().NotBe(hash2);
}
[Fact]
public void ComputeContentHash_IncludesAnnotations()
{
var annotations = new Dictionary<string, string> { ["key"] = "value" };
var hash1 = EffectiveFinding.ComputeContentHash("affected", "High", null, null, annotations);
var hash2 = EffectiveFinding.ComputeContentHash("affected", "High", null, null, null);
hash1.Should().NotBe(hash2);
}
[Fact]
public void ComputeContentHash_SortsAnnotationsDeterministically()
{
var annotations1 = new Dictionary<string, string> { ["a"] = "1", ["b"] = "2" };
var annotations2 = new Dictionary<string, string> { ["b"] = "2", ["a"] = "1" };
var hash1 = EffectiveFinding.ComputeContentHash("affected", null, null, null, annotations1);
var hash2 = EffectiveFinding.ComputeContentHash("affected", null, null, null, annotations2);
hash1.Should().Be(hash2);
}
#endregion
#region EffectiveFindingHistoryEntry Tests
[Fact]
public void HistoryEntry_CreateId_IsDeterministic()
{
var id1 = EffectiveFindingHistoryEntry.CreateId("finding-1", 5);
var id2 = EffectiveFindingHistoryEntry.CreateId("finding-1", 5);
id1.Should().Be(id2);
id1.Should().Be("finding-1:v5");
}
[Fact]
public void HistoryEntry_CreateId_DiffersForDifferentVersion()
{
var id1 = EffectiveFindingHistoryEntry.CreateId("finding-1", 1);
var id2 = EffectiveFindingHistoryEntry.CreateId("finding-1", 2);
id1.Should().NotBe(id2);
}
#endregion
#region MaterializeFindingInput Tests
[Fact]
public void MaterializeFindingInput_CanBeCreated()
{
var input = new MaterializeFindingInput
{
TenantId = "tenant-1",
PolicyId = "policy-1",
PolicyVersion = 1,
ComponentPurl = "pkg:npm/lodash@4.17.21",
ComponentName = "lodash",
ComponentVersion = "4.17.21",
AdvisoryId = "CVE-2021-12345",
AdvisorySource = "nvd",
Status = "affected",
Severity = "High",
RuleName = "severity-rule",
VexStatus = "not_affected",
VexJustification = "vulnerable_code_not_in_execute_path",
Annotations = ImmutableDictionary<string, string>.Empty.Add("key", "value"),
PolicyRunId = "run-123",
TraceId = "trace-abc",
SpanId = "span-def"
};
input.TenantId.Should().Be("tenant-1");
input.PolicyId.Should().Be("policy-1");
input.PolicyVersion.Should().Be(1);
input.ComponentPurl.Should().Be("pkg:npm/lodash@4.17.21");
input.Status.Should().Be("affected");
input.VexStatus.Should().Be("not_affected");
}
#endregion
#region MaterializeFindingResult Tests
[Fact]
public void MaterializeFindingResult_TracksCreation()
{
var result = new MaterializeFindingResult
{
FindingId = "sha256:abc123",
WasCreated = true,
WasUpdated = false,
HistoryVersion = 1,
ChangeType = EffectiveFindingChangeType.Created
};
result.WasCreated.Should().BeTrue();
result.WasUpdated.Should().BeFalse();
result.ChangeType.Should().Be(EffectiveFindingChangeType.Created);
}
[Fact]
public void MaterializeFindingResult_TracksUpdate()
{
var result = new MaterializeFindingResult
{
FindingId = "sha256:abc123",
WasCreated = false,
WasUpdated = true,
HistoryVersion = 2,
ChangeType = EffectiveFindingChangeType.StatusChanged
};
result.WasCreated.Should().BeFalse();
result.WasUpdated.Should().BeTrue();
result.ChangeType.Should().Be(EffectiveFindingChangeType.StatusChanged);
}
#endregion
#region MaterializeBatchResult Tests
[Fact]
public void MaterializeBatchResult_AggregatesCorrectly()
{
var results = ImmutableArray.Create(
new MaterializeFindingResult
{
FindingId = "id1",
WasCreated = true,
WasUpdated = false,
HistoryVersion = 1,
ChangeType = EffectiveFindingChangeType.Created
},
new MaterializeFindingResult
{
FindingId = "id2",
WasCreated = false,
WasUpdated = true,
HistoryVersion = 2,
ChangeType = EffectiveFindingChangeType.StatusChanged
}
);
var batchResult = new MaterializeBatchResult
{
TotalInputs = 3,
Created = 1,
Updated = 1,
Unchanged = 1,
Errors = 0,
ProcessingTimeMs = 100,
Results = results
};
batchResult.TotalInputs.Should().Be(3);
batchResult.Created.Should().Be(1);
batchResult.Updated.Should().Be(1);
batchResult.Unchanged.Should().Be(1);
batchResult.Results.Should().HaveCount(2);
}
#endregion
#region EffectiveFindingChangeType Tests
[Theory]
[InlineData(EffectiveFindingChangeType.Created, "Created")]
[InlineData(EffectiveFindingChangeType.StatusChanged, "StatusChanged")]
[InlineData(EffectiveFindingChangeType.SeverityChanged, "SeverityChanged")]
[InlineData(EffectiveFindingChangeType.VexApplied, "VexApplied")]
[InlineData(EffectiveFindingChangeType.AnnotationsChanged, "AnnotationsChanged")]
[InlineData(EffectiveFindingChangeType.PolicyVersionChanged, "PolicyVersionChanged")]
public void EffectiveFindingChangeType_HasExpectedValues(EffectiveFindingChangeType changeType, string expectedName)
{
changeType.ToString().Should().Be(expectedName);
}
#endregion
}