namespace StellaOps.Interop.Tests.Spdx; [Trait("Category", "Interop")] [Trait("Format", "SPDX")] public class SpdxRoundTripTests : IClassFixture { private readonly InteropTestHarness _harness; public SpdxRoundTripTests(InteropTestHarness harness) { _harness = harness; } [Theory] [MemberData(nameof(TestImages))] public async Task Syft_GeneratesSpdx_CanBeParsed(string imageRef) { // Generate SBOM with Syft var sbomResult = await _harness.GenerateSbomWithSyft( imageRef, SbomFormat.Spdx30); sbomResult.Success.Should().BeTrue("Syft should generate SPDX SBOM"); // Validate basic SPDX structure sbomResult.Content.Should().Contain("spdxVersion"); sbomResult.Content.Should().Contain("SPDX-3.0"); } [Theory] [MemberData(nameof(TestImages))] public async Task Stella_GeneratesSpdx_CanBeParsed(string imageRef) { // Generate SBOM with Stella var sbomResult = await _harness.GenerateSbomWithStella( imageRef, SbomFormat.Spdx30); sbomResult.Success.Should().BeTrue("Stella should generate SPDX SBOM"); // Validate basic SPDX structure sbomResult.Content.Should().Contain("spdxVersion"); sbomResult.Content.Should().Contain("SPDX-3.0"); } [Theory] [MemberData(nameof(TestImages))] [Trait("Category", "Schema")] public async Task Stella_Spdx_ValidatesAgainstSchema(string imageRef) { // Generate SBOM var sbomResult = await _harness.GenerateSbomWithStella( imageRef, SbomFormat.Spdx30); sbomResult.Success.Should().BeTrue(); // TODO: Validate against SPDX 3.0.1 JSON schema sbomResult.Content.Should().NotBeNullOrEmpty(); sbomResult.Content.Should().Contain("\"spdxVersion\""); sbomResult.Content.Should().Contain("\"creationInfo\""); } [Fact] [Trait("Category", "EvidenceChain")] public async Task Spdx_IncludesEvidenceChain() { var imageRef = "alpine:3.18"; // Generate SBOM with evidence var sbomResult = await _harness.GenerateSbomWithStella( imageRef, SbomFormat.Spdx30); sbomResult.Success.Should().BeTrue(); // TODO: Verify evidence chain is included in SPDX document // SPDX 3.0 supports relationships that can express evidence chains sbomResult.Content.Should().Contain("\"relationships\""); } [Fact] [Trait("Category", "Interop")] public async Task Spdx_CompatibleWithConsumers() { var imageRef = "debian:12-slim"; // Generate SBOM var sbomResult = await _harness.GenerateSbomWithStella( imageRef, SbomFormat.Spdx30); sbomResult.Success.Should().BeTrue(); // TODO: Test with SPDX consumers/validators // For now, just verify structure sbomResult.Content.Should().NotBeNullOrEmpty(); } public static IEnumerable TestImages => [ ["alpine:3.18"], ["debian:12-slim"], ["ubuntu:22.04"], ["python:3.12-slim"], ["node:20-alpine"] ]; }