Files
git.stella-ops.org/src/__Libraries/StellaOps.Resolver.Tests/VerdictDigestTests.cs

161 lines
5.5 KiB
C#

/**
* VerdictDigest Tests
* Sprint: SPRINT_9100_0002_0002 (Per-Node VerdictDigest)
* Tasks: VDIGEST-9100-016 through VDIGEST-9100-021
*/
using System.Text.Json;
using Xunit;
using StellaOps.TestKit;
namespace StellaOps.Resolver.Tests;
public class VerdictDigestTests
{
[Trait("Category", TestCategories.Unit)]
[Fact]
public void VerdictDigest_IsDeterministic()
{
// VDIGEST-9100-016: Same verdict → same digest
var nodeId = NodeId.From("package", "test");
var evidence = JsonDocument.Parse("{\"reason\": \"test\"}").RootElement;
var verdict1 = Verdict.Create(nodeId, VerdictStatus.Pass, evidence, "Test reason", 0);
var verdict2 = Verdict.Create(nodeId, VerdictStatus.Pass, evidence, "Test reason", 0);
Assert.Equal(verdict1.VerdictDigest, verdict2.VerdictDigest);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void VerdictDigest_ChangesWhenStatusChanges()
{
// VDIGEST-9100-017: Digest changes with status
var nodeId = NodeId.From("package", "test");
var evidence = JsonDocument.Parse("{\"reason\": \"test\"}").RootElement;
var passVerdict = Verdict.Create(nodeId, VerdictStatus.Pass, evidence);
var failVerdict = Verdict.Create(nodeId, VerdictStatus.Fail, evidence);
Assert.NotEqual(passVerdict.VerdictDigest, failVerdict.VerdictDigest);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void VerdictDigest_ChangesWhenEvidenceChanges()
{
// VDIGEST-9100-018: Digest changes with evidence
var nodeId = NodeId.From("package", "test");
var evidence1 = JsonDocument.Parse("{\"reason\": \"reason1\"}").RootElement;
var evidence2 = JsonDocument.Parse("{\"reason\": \"reason2\"}").RootElement;
var verdict1 = Verdict.Create(nodeId, VerdictStatus.Pass, evidence1);
var verdict2 = Verdict.Create(nodeId, VerdictStatus.Pass, evidence2);
Assert.NotEqual(verdict1.VerdictDigest, verdict2.VerdictDigest);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void VerdictDelta_CorrectlyIdentifiesChangedVerdicts()
{
// VDIGEST-9100-019: Delta detection identifies changed verdicts
var nodeId1 = NodeId.From("package", "a");
var nodeId2 = NodeId.From("package", "b");
var oldVerdicts = new[]
{
Verdict.Create(nodeId1, VerdictStatus.Pass, null),
Verdict.Create(nodeId2, VerdictStatus.Pass, null)
};
var newVerdicts = new[]
{
Verdict.Create(nodeId1, VerdictStatus.Pass, null),
Verdict.Create(nodeId2, VerdictStatus.Fail, null) // Changed
};
var oldResult = new ResolutionResult
{
TraversalSequence = [nodeId1, nodeId2],
Verdicts = [.. oldVerdicts],
GraphDigest = "abc",
PolicyDigest = "def",
FinalDigest = "old"
};
var newResult = new ResolutionResult
{
TraversalSequence = [nodeId1, nodeId2],
Verdicts = [.. newVerdicts],
GraphDigest = "abc",
PolicyDigest = "def",
FinalDigest = "new"
};
var detector = new DefaultVerdictDeltaDetector();
var delta = detector.Detect(oldResult, newResult);
Assert.Single(delta.ChangedVerdicts);
Assert.Equal(nodeId2, delta.ChangedVerdicts[0].Old.Node);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void VerdictDelta_HandlesAddedRemovedNodes()
{
// VDIGEST-9100-020: Delta handles added/removed nodes
var nodeId1 = NodeId.From("package", "a");
var nodeId2 = NodeId.From("package", "b");
var nodeId3 = NodeId.From("package", "c");
var oldResult = new ResolutionResult
{
TraversalSequence = [nodeId1, nodeId2],
Verdicts = [
Verdict.Create(nodeId1, VerdictStatus.Pass, null),
Verdict.Create(nodeId2, VerdictStatus.Pass, null)
],
GraphDigest = "abc",
PolicyDigest = "def",
FinalDigest = "old"
};
var newResult = new ResolutionResult
{
TraversalSequence = [nodeId1, nodeId3],
Verdicts = [
Verdict.Create(nodeId1, VerdictStatus.Pass, null),
Verdict.Create(nodeId3, VerdictStatus.Pass, null)
],
GraphDigest = "abc",
PolicyDigest = "def",
FinalDigest = "new"
};
var detector = new DefaultVerdictDeltaDetector();
var delta = detector.Detect(oldResult, newResult);
Assert.Single(delta.AddedVerdicts);
Assert.Single(delta.RemovedVerdicts);
Assert.Equal(nodeId3, delta.AddedVerdicts[0].Node);
Assert.Equal(nodeId2, delta.RemovedVerdicts[0].Node);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void VerdictDigest_ExcludesItselfFromComputation()
{
// VDIGEST-9100-021: Property test - no recursion
var nodeId = NodeId.From("package", "test");
// Create two verdicts with the same input data
var verdict1 = Verdict.Create(nodeId, VerdictStatus.Pass, null, "reason", 0);
var verdict2 = Verdict.Create(nodeId, VerdictStatus.Pass, null, "reason", 0);
// Digests should be identical and stable (not including themselves)
Assert.Equal(verdict1.VerdictDigest, verdict2.VerdictDigest);
Assert.Equal(64, verdict1.VerdictDigest.Length); // Valid SHA256
}
}