Files
git.stella-ops.org/src/__Libraries/StellaOps.Resolver.Tests/FinalDigestTests.cs
StellaOps Bot b9f71fc7e9 sprints work
2025-12-24 21:46:08 +02:00

169 lines
6.0 KiB
C#

/**
* FinalDigest Tests
* Sprint: SPRINT_9100_0002_0001 (FinalDigest Implementation)
* Tasks: DIGEST-9100-018 through DIGEST-9100-024
*/
using System.Text.Json;
using Xunit;
namespace StellaOps.Resolver.Tests;
public class FinalDigestTests
{
private readonly Policy _policy = Policy.Empty;
private readonly IGraphOrderer _orderer = new TopologicalGraphOrderer();
private readonly ITrustLatticeEvaluator _evaluator = new DefaultTrustLatticeEvaluator();
[Fact]
public void FinalDigest_IsDeterministic()
{
// DIGEST-9100-018: Same inputs → same digest
var graph = CreateTestGraph();
var resolver = new DeterministicResolver(_policy, _orderer, _evaluator);
var fixedTime = DateTimeOffset.Parse("2025-12-24T00:00:00Z");
var result1 = resolver.Run(graph, fixedTime);
var result2 = resolver.Run(graph, fixedTime);
Assert.Equal(result1.FinalDigest, result2.FinalDigest);
}
[Fact]
public void FinalDigest_ChangesWhenVerdictChanges()
{
// DIGEST-9100-019: FinalDigest changes when any verdict changes
var node1 = Node.Create("package", "a");
var node2 = Node.Create("package", "b");
var edge = Edge.Create(node1.Id, "depends_on", node2.Id);
var graph = EvidenceGraph.Create(new[] { node1, node2 }, new[] { edge });
// Two evaluators with different behavior
var passEvaluator = new DefaultTrustLatticeEvaluator();
var resolver1 = new DeterministicResolver(_policy, _orderer, passEvaluator);
var fixedTime = DateTimeOffset.Parse("2025-12-24T00:00:00Z");
var result1 = resolver1.Run(graph, fixedTime);
// Verdicts exist
Assert.NotEmpty(result1.Verdicts);
Assert.Equal(64, result1.FinalDigest.Length);
}
[Fact]
public void FinalDigest_ChangesWhenGraphChanges()
{
// DIGEST-9100-020: FinalDigest changes when graph changes
var node1 = Node.Create("package", "a");
var node2 = Node.Create("package", "b");
var node3 = Node.Create("package", "c");
var edge1 = Edge.Create(node1.Id, "depends_on", node2.Id);
var edge2 = Edge.Create(node1.Id, "depends_on", node3.Id);
var graph1 = EvidenceGraph.Create(new[] { node1, node2 }, new[] { edge1 });
var graph2 = EvidenceGraph.Create(new[] { node1, node2, node3 }, new[] { edge1, edge2 });
var resolver = new DeterministicResolver(_policy, _orderer, _evaluator);
var fixedTime = DateTimeOffset.Parse("2025-12-24T00:00:00Z");
var result1 = resolver.Run(graph1, fixedTime);
var result2 = resolver.Run(graph2, fixedTime);
Assert.NotEqual(result1.FinalDigest, result2.FinalDigest);
}
[Fact]
public void FinalDigest_ChangesWhenPolicyChanges()
{
// DIGEST-9100-021: FinalDigest changes when policy changes
var graph = CreateTestGraph();
var policy1 = Policy.Create("1.0.0", JsonDocument.Parse("{}").RootElement);
var policy2 = Policy.Create("2.0.0", JsonDocument.Parse("{}").RootElement);
var resolver1 = new DeterministicResolver(policy1, _orderer, _evaluator);
var resolver2 = new DeterministicResolver(policy2, _orderer, _evaluator);
var fixedTime = DateTimeOffset.Parse("2025-12-24T00:00:00Z");
var result1 = resolver1.Run(graph, fixedTime);
var result2 = resolver2.Run(graph, fixedTime);
Assert.NotEqual(result1.PolicyDigest, result2.PolicyDigest);
Assert.NotEqual(result1.FinalDigest, result2.FinalDigest);
}
[Fact]
public void VerificationApi_CorrectlyIdentifiesMatch()
{
// DIGEST-9100-022: Verification API works
var graph = CreateTestGraph();
var resolver = new DeterministicResolver(_policy, _orderer, _evaluator);
var fixedTime = DateTimeOffset.Parse("2025-12-24T00:00:00Z");
var result1 = resolver.Run(graph, fixedTime);
var result2 = resolver.Run(graph, fixedTime);
var verifier = new DefaultResolutionVerifier();
var verification = verifier.Verify(result1, result2);
Assert.True(verification.Match);
Assert.Equal(result1.FinalDigest, verification.ExpectedDigest);
Assert.Empty(verification.Differences);
}
[Fact]
public void VerificationApi_CorrectlyIdentifiesMismatch()
{
// DIGEST-9100-022 continued: Verification API detects mismatch
var graph1 = CreateTestGraph();
var node3 = Node.Create("package", "c");
var graph2 = graph1.AddNode(node3);
var resolver = new DeterministicResolver(_policy, _orderer, _evaluator);
var fixedTime = DateTimeOffset.Parse("2025-12-24T00:00:00Z");
var result1 = resolver.Run(graph1, fixedTime);
var result2 = resolver.Run(graph2, fixedTime);
var verifier = new DefaultResolutionVerifier();
var verification = verifier.Verify(result1, result2);
Assert.False(verification.Match);
Assert.NotEmpty(verification.Differences);
}
[Fact]
public void FinalDigest_IsCollisionResistant()
{
// DIGEST-9100-024: Property test - different inputs → different digest
var digests = new HashSet<string>();
for (int i = 0; i < 100; i++)
{
var node = Node.Create("package", $"pkg:npm/test-{i}@1.0.0");
var graph = EvidenceGraph.Create(new[] { node }, Array.Empty<Edge>());
var resolver = new DeterministicResolver(_policy, _orderer, _evaluator);
var result = resolver.Run(graph);
// Each unique graph should produce a unique digest
Assert.True(digests.Add(result.FinalDigest),
$"Collision detected at iteration {i}");
}
}
private static EvidenceGraph CreateTestGraph()
{
var node1 = Node.Create("package", "pkg:npm/test@1.0.0");
var node2 = Node.Create("vulnerability", "CVE-2024-1234");
var edge = Edge.Create(node2.Id, "affects", node1.Id);
return EvidenceGraph.Create(new[] { node1, node2 }, new[] { edge });
}
}