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:
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"schema": "scheduler-impact-index@1",
|
||||
"generatedAt": "2025-10-01T00:00:00Z",
|
||||
"image": {
|
||||
"repository": "registry.stellaops.test/team/sample-service",
|
||||
"digest": "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
|
||||
"tag": "1.0.0"
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
"purl": "pkg:docker/sample-service@1.0.0",
|
||||
"usage": [
|
||||
"runtime"
|
||||
]
|
||||
},
|
||||
{
|
||||
"purl": "pkg:pypi/requests@2.31.0",
|
||||
"usage": [
|
||||
"usedByEntrypoint"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -3,11 +3,11 @@ using System.Buffers.Binary;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Collections.Special;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using StellaOps.Cryptography;
|
||||
using StellaOps.Scheduler.ImpactIndex.Ingestion;
|
||||
using StellaOps.Scheduler.Models;
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace StellaOps.Scheduler.ImpactIndex;
|
||||
/// </summary>
|
||||
public sealed class RoaringImpactIndex : IImpactIndex
|
||||
{
|
||||
private static readonly ICryptoHash Hash = CryptoHashFactory.CreateDefault();
|
||||
private readonly object _gate = new();
|
||||
|
||||
private readonly Dictionary<string, int> _imageIds = new(StringComparer.OrdinalIgnoreCase);
|
||||
@@ -570,8 +571,8 @@ public sealed class RoaringImpactIndex : IImpactIndex
|
||||
AppendMap(contains);
|
||||
AppendMap(usedBy);
|
||||
|
||||
var hash = SHA256.HashData(Encoding.UTF8.GetBytes(builder.ToString()));
|
||||
return "snap-" + Convert.ToHexString(hash).ToLowerInvariant();
|
||||
var hashHex = Hash.ComputeHashHex(Encoding.UTF8.GetBytes(builder.ToString()), HashAlgorithms.Sha256);
|
||||
return "snap-" + hashHex;
|
||||
}
|
||||
|
||||
private static bool MatchesTagPattern(string tag, string pattern)
|
||||
@@ -620,7 +621,7 @@ public sealed class RoaringImpactIndex : IImpactIndex
|
||||
|
||||
private static int ComputeDeterministicId(string digest)
|
||||
{
|
||||
var bytes = SHA256.HashData(Encoding.UTF8.GetBytes(digest));
|
||||
var bytes = Hash.ComputeHash(Encoding.UTF8.GetBytes(digest), HashAlgorithms.Sha256);
|
||||
for (var offset = 0; offset <= bytes.Length - sizeof(int); offset += sizeof(int))
|
||||
{
|
||||
var value = BinaryPrimitives.ReadInt32LittleEndian(bytes.AsSpan(offset, sizeof(int))) & int.MaxValue;
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../StellaOps.Scheduler.Models/StellaOps.Scheduler.Models.csproj" />
|
||||
<ProjectReference Include="../../../__Libraries/StellaOps.Cryptography/StellaOps.Cryptography.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Fixtures\**\*.json" />
|
||||
<EmbeddedResource Include="..\..\samples\scanner\images\**\bom-index.json"
|
||||
<EmbeddedResource Include="..\..\..\..\samples\scanner\images\**\bom-index.json"
|
||||
Link="Fixtures\%(RecursiveDir)%(Filename)%(Extension)" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user