Add tests for SBOM generation determinism across multiple formats
- Created `StellaOps.TestKit.Tests` project for unit tests related to determinism. - Implemented `DeterminismManifestTests` to validate deterministic output for canonical bytes and strings, file read/write operations, and error handling for invalid schema versions. - Added `SbomDeterminismTests` to ensure identical inputs produce consistent SBOMs across SPDX 3.0.1 and CycloneDX 1.6/1.7 formats, including parallel execution tests. - Updated project references in `StellaOps.Integration.Determinism` to include the new determinism testing library.
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
using System.Reflection;
|
||||
using NetArchTest.Rules;
|
||||
using Xunit;
|
||||
using FluentAssertions;
|
||||
|
||||
namespace StellaOps.Architecture.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Architecture tests for lattice engine placement rules.
|
||||
/// Ensures lattice algorithms are only in Scanner.WebService, not in Concelier or Excititor.
|
||||
/// </summary>
|
||||
[Trait("Category", "Architecture")]
|
||||
public sealed class LatticeEngineRulesTests
|
||||
{
|
||||
private const string ScannerLatticeNamespace = "StellaOps.Scanner.Lattice";
|
||||
|
||||
/// <summary>
|
||||
/// Concelier modules must not reference Scanner lattice engine.
|
||||
/// Lattice decisions are made in Scanner, not in Concelier.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Concelier_MustNot_Reference_ScannerLattice()
|
||||
{
|
||||
var concelierAssemblies = GetAssembliesByPattern("StellaOps.Concelier");
|
||||
|
||||
if (!concelierAssemblies.Any())
|
||||
{
|
||||
// Skip if assemblies not loaded (test discovery phase)
|
||||
return;
|
||||
}
|
||||
|
||||
var result = Types.InAssemblies(concelierAssemblies)
|
||||
.ShouldNot()
|
||||
.HaveDependencyOn(ScannerLatticeNamespace)
|
||||
.GetResult();
|
||||
|
||||
result.IsSuccessful.Should().BeTrue(
|
||||
$"Concelier assemblies must not reference Scanner lattice. " +
|
||||
$"Violations: {string.Join(", ", result.FailingTypeNames ?? Enumerable.Empty<string>())}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Excititor modules must not reference Scanner lattice engine.
|
||||
/// Excititor preserves prune source - does not evaluate lattice decisions.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Excititor_MustNot_Reference_ScannerLattice()
|
||||
{
|
||||
var excititorAssemblies = GetAssembliesByPattern("StellaOps.Excititor");
|
||||
|
||||
if (!excititorAssemblies.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var result = Types.InAssemblies(excititorAssemblies)
|
||||
.ShouldNot()
|
||||
.HaveDependencyOn(ScannerLatticeNamespace)
|
||||
.GetResult();
|
||||
|
||||
result.IsSuccessful.Should().BeTrue(
|
||||
$"Excititor assemblies must not reference Scanner lattice. " +
|
||||
$"Violations: {string.Join(", ", result.FailingTypeNames ?? Enumerable.Empty<string>())}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scanner.WebService MAY reference Scanner lattice engine (it's the authorized host).
|
||||
/// This test documents the allowed dependency.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void ScannerWebService_May_Reference_ScannerLattice()
|
||||
{
|
||||
// This is a documentation test - Scanner.WebService is allowed to use lattice
|
||||
// The test validates that the architectural rule is correctly documented
|
||||
var allowedAssemblies = new[] { "StellaOps.Scanner.WebService" };
|
||||
|
||||
// Positive assertion: these assemblies ARE allowed to reference lattice
|
||||
allowedAssemblies.Should().Contain("StellaOps.Scanner.WebService",
|
||||
"Scanner.WebService is the authorized host for lattice algorithms");
|
||||
}
|
||||
|
||||
private static IEnumerable<Assembly> GetAssembliesByPattern(string pattern)
|
||||
{
|
||||
return AppDomain.CurrentDomain.GetAssemblies()
|
||||
.Where(a => a.GetName().Name?.StartsWith(pattern) == true);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user