Files
git.stella-ops.org/src/Scanner/__Tests/StellaOps.Scanner.Emit.Lineage.Tests/RebuildProofTests.cs

333 lines
9.6 KiB
C#

// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (c) StellaOps
using System.Collections.Immutable;
using FluentAssertions;
using StellaOps.Scanner.Emit.Lineage;
using StellaOps.TestKit;
namespace StellaOps.Scanner.Emit.Lineage.Tests;
public class RebuildProofTests
{
#region RebuildProof Model Tests
[Trait("Category", TestCategories.Unit)]
[Fact]
public void RebuildProof_RequiredProperties_MustBeSet()
{
var proof = new RebuildProof
{
SbomId = SbomId.New(),
ImageDigest = "sha256:abc123",
StellaOpsVersion = "1.0.0",
FeedSnapshots = [],
AnalyzerVersions = [],
PolicyHash = "sha256:policy",
GeneratedAt = DateTimeOffset.UtcNow
};
proof.SbomId.Should().NotBe(default(SbomId));
proof.ImageDigest.Should().NotBeNullOrEmpty();
proof.StellaOpsVersion.Should().Be("1.0.0");
proof.PolicyHash.Should().NotBeNullOrEmpty();
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void RebuildProof_WithFeedSnapshots_TracksAllFeeds()
{
var feeds = ImmutableArray.Create(
new FeedSnapshot
{
FeedId = "nvd",
FeedName = "NVD CVE Feed",
SnapshotHash = "sha256:nvdhash",
AsOf = DateTimeOffset.UtcNow,
EntryCount = 200000
},
new FeedSnapshot
{
FeedId = "ghsa",
FeedName = "GitHub Security Advisories",
SnapshotHash = "sha256:ghsahash",
AsOf = DateTimeOffset.UtcNow,
EntryCount = 15000
}
);
var proof = new RebuildProof
{
SbomId = SbomId.New(),
ImageDigest = "sha256:image",
StellaOpsVersion = "1.0.0",
FeedSnapshots = feeds,
AnalyzerVersions = [],
PolicyHash = "sha256:policy",
GeneratedAt = DateTimeOffset.UtcNow
};
proof.FeedSnapshots.Should().HaveCount(2);
proof.FeedSnapshots[0].FeedId.Should().Be("nvd");
proof.FeedSnapshots[1].EntryCount.Should().Be(15000);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void RebuildProof_WithAnalyzerVersions_TracksAllAnalyzers()
{
var analyzers = ImmutableArray.Create(
new AnalyzerVersion
{
AnalyzerId = "npm-analyzer",
AnalyzerName = "NPM Package Analyzer",
Version = "2.0.0",
CodeHash = "sha256:npmhash"
},
new AnalyzerVersion
{
AnalyzerId = "dotnet-analyzer",
AnalyzerName = ".NET Package Analyzer",
Version = "3.1.0"
}
);
var proof = new RebuildProof
{
SbomId = SbomId.New(),
ImageDigest = "sha256:image",
StellaOpsVersion = "1.0.0",
FeedSnapshots = [],
AnalyzerVersions = analyzers,
PolicyHash = "sha256:policy",
GeneratedAt = DateTimeOffset.UtcNow
};
proof.AnalyzerVersions.Should().HaveCount(2);
proof.AnalyzerVersions[0].AnalyzerId.Should().Be("npm-analyzer");
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void RebuildProof_OptionalDsseSignature_IsNullByDefault()
{
var proof = new RebuildProof
{
SbomId = SbomId.New(),
ImageDigest = "sha256:image",
StellaOpsVersion = "1.0.0",
FeedSnapshots = [],
AnalyzerVersions = [],
PolicyHash = "sha256:policy",
GeneratedAt = DateTimeOffset.UtcNow
};
proof.DsseSignature.Should().BeNull();
proof.ProofHash.Should().BeNull();
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void RebuildProof_WithSignature_StoresSignature()
{
var proof = new RebuildProof
{
SbomId = SbomId.New(),
ImageDigest = "sha256:image",
StellaOpsVersion = "1.0.0",
FeedSnapshots = [],
AnalyzerVersions = [],
PolicyHash = "sha256:policy",
GeneratedAt = DateTimeOffset.UtcNow,
DsseSignature = "eyJwYXlsb2FkIjoiLi4uIn0=",
ProofHash = "sha256:proofhash"
};
proof.DsseSignature.Should().NotBeNullOrEmpty();
proof.ProofHash.Should().StartWith("sha256:");
}
#endregion
#region FeedSnapshot Tests
[Trait("Category", TestCategories.Unit)]
[Fact]
public void FeedSnapshot_RequiredProperties_MustBeSet()
{
var snapshot = new FeedSnapshot
{
FeedId = "nvd",
FeedName = "NVD CVE Feed",
SnapshotHash = "sha256:hash",
AsOf = DateTimeOffset.UtcNow
};
snapshot.FeedId.Should().Be("nvd");
snapshot.FeedName.Should().Be("NVD CVE Feed");
snapshot.SnapshotHash.Should().NotBeNullOrEmpty();
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void FeedSnapshot_OptionalProperties_AreNullByDefault()
{
var snapshot = new FeedSnapshot
{
FeedId = "nvd",
FeedName = "NVD",
SnapshotHash = "sha256:hash",
AsOf = DateTimeOffset.UtcNow
};
snapshot.EntryCount.Should().BeNull();
snapshot.FeedVersion.Should().BeNull();
}
#endregion
#region AnalyzerVersion Tests
[Trait("Category", TestCategories.Unit)]
[Fact]
public void AnalyzerVersion_RequiredProperties_MustBeSet()
{
var analyzer = new AnalyzerVersion
{
AnalyzerId = "npm-analyzer",
AnalyzerName = "NPM Package Analyzer",
Version = "2.0.0"
};
analyzer.AnalyzerId.Should().Be("npm-analyzer");
analyzer.AnalyzerName.Should().Be("NPM Package Analyzer");
analyzer.Version.Should().Be("2.0.0");
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void AnalyzerVersion_OptionalHashes_AreNullByDefault()
{
var analyzer = new AnalyzerVersion
{
AnalyzerId = "test",
AnalyzerName = "Test",
Version = "1.0.0"
};
analyzer.CodeHash.Should().BeNull();
analyzer.ConfigHash.Should().BeNull();
}
#endregion
#region RebuildVerification Tests
[Trait("Category", TestCategories.Unit)]
[Fact]
public void RebuildVerification_SuccessfulRebuild_HasMatchingHash()
{
var proof = new RebuildProof
{
SbomId = SbomId.New(),
ImageDigest = "sha256:image",
StellaOpsVersion = "1.0.0",
FeedSnapshots = [],
AnalyzerVersions = [],
PolicyHash = "sha256:policy",
GeneratedAt = DateTimeOffset.UtcNow
};
var verification = new RebuildVerification
{
Proof = proof,
Success = true,
RebuiltSbomId = SbomId.New(),
HashMatches = true,
VerifiedAt = DateTimeOffset.UtcNow
};
verification.Success.Should().BeTrue();
verification.HashMatches.Should().BeTrue();
verification.Differences.Should().BeNull();
verification.ErrorMessage.Should().BeNull();
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void RebuildVerification_FailedRebuild_HasErrorMessage()
{
var proof = new RebuildProof
{
SbomId = SbomId.New(),
ImageDigest = "sha256:image",
StellaOpsVersion = "1.0.0",
FeedSnapshots = [],
AnalyzerVersions = [],
PolicyHash = "sha256:policy",
GeneratedAt = DateTimeOffset.UtcNow
};
var verification = new RebuildVerification
{
Proof = proof,
Success = false,
ErrorMessage = "Feed snapshot not available",
VerifiedAt = DateTimeOffset.UtcNow
};
verification.Success.Should().BeFalse();
verification.ErrorMessage.Should().Be("Feed snapshot not available");
verification.RebuiltSbomId.Should().BeNull();
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void RebuildVerification_MismatchRebuild_HasDifferences()
{
var proof = new RebuildProof
{
SbomId = SbomId.New(),
ImageDigest = "sha256:image",
StellaOpsVersion = "1.0.0",
FeedSnapshots = [],
AnalyzerVersions = [],
PolicyHash = "sha256:policy",
GeneratedAt = DateTimeOffset.UtcNow
};
var diff = new SbomDiff
{
FromId = proof.SbomId,
ToId = SbomId.New(),
Deltas = [],
Summary = new DiffSummary
{
Added = 1,
Removed = 0,
VersionChanged = 0,
OtherModified = 0,
Unchanged = 100
},
ComputedAt = DateTimeOffset.UtcNow
};
var verification = new RebuildVerification
{
Proof = proof,
Success = true,
RebuiltSbomId = SbomId.New(),
HashMatches = false,
Differences = diff,
VerifiedAt = DateTimeOffset.UtcNow
};
verification.Success.Should().BeTrue();
verification.HashMatches.Should().BeFalse();
verification.Differences.Should().NotBeNull();
verification.Differences!.Summary.Added.Should().Be(1);
}
#endregion
}