audit, advisories and doctors/setup work

This commit is contained in:
master
2026-01-13 18:53:39 +02:00
parent 9ca7cb183e
commit d7be6ba34b
811 changed files with 54242 additions and 4056 deletions

View File

@@ -1,9 +1,9 @@
using FluentAssertions;
using StellaOps.Provcache;
using StellaOps.TestKit;
using StellaOps.TestKit.Deterministic;
using Xunit;
using StellaOps.TestKit;
namespace StellaOps.Provcache.Tests;
/// <summary>
@@ -11,6 +11,7 @@ namespace StellaOps.Provcache.Tests;
/// </summary>
public sealed class EvidenceChunkerTests
{
private static readonly DateTimeOffset FixedNow = new(2026, 1, 1, 0, 0, 0, TimeSpan.Zero);
private readonly ProvcacheOptions _options;
private readonly EvidenceChunker _chunker;
@@ -21,12 +22,11 @@ public sealed class EvidenceChunkerTests
}
[Trait("Category", TestCategories.Unit)]
[Fact]
[Fact]
public async Task ChunkAsync_ShouldSplitEvidenceIntoMultipleChunks_WhenLargerThanChunkSize()
{
// Arrange
var evidence = new byte[200];
Random.Shared.NextBytes(evidence);
var evidence = CreateDeterministicBytes(200, 1);
const string contentType = "application/octet-stream";
// Act
@@ -48,12 +48,11 @@ public sealed class EvidenceChunkerTests
}
[Trait("Category", TestCategories.Unit)]
[Fact]
[Fact]
public async Task ChunkAsync_ShouldCreateSingleChunk_WhenSmallerThanChunkSize()
{
// Arrange
var evidence = new byte[32];
Random.Shared.NextBytes(evidence);
var evidence = CreateDeterministicBytes(32, 2);
const string contentType = "application/json";
// Act
@@ -67,7 +66,7 @@ public sealed class EvidenceChunkerTests
}
[Trait("Category", TestCategories.Unit)]
[Fact]
[Fact]
public async Task ChunkAsync_ShouldHandleEmptyEvidence()
{
// Arrange
@@ -84,7 +83,7 @@ public sealed class EvidenceChunkerTests
}
[Trait("Category", TestCategories.Unit)]
[Fact]
[Fact]
public async Task ChunkAsync_ShouldProduceUniqueHashForEachChunk()
{
// Arrange - create evidence with distinct bytes per chunk
@@ -102,12 +101,11 @@ public sealed class EvidenceChunkerTests
}
[Trait("Category", TestCategories.Unit)]
[Fact]
[Fact]
public async Task ReassembleAsync_ShouldRecoverOriginalEvidence()
{
// Arrange
var original = new byte[200];
Random.Shared.NextBytes(original);
var original = CreateDeterministicBytes(200, 3);
const string contentType = "application/octet-stream";
var chunked = await _chunker.ChunkAsync(original, contentType);
@@ -120,12 +118,11 @@ public sealed class EvidenceChunkerTests
}
[Trait("Category", TestCategories.Unit)]
[Fact]
[Fact]
public async Task ReassembleAsync_ShouldThrow_WhenMerkleRootMismatch()
{
// Arrange
var evidence = new byte[100];
Random.Shared.NextBytes(evidence);
var evidence = CreateDeterministicBytes(100, 4);
const string contentType = "application/octet-stream";
var chunked = await _chunker.ChunkAsync(evidence, contentType);
@@ -137,12 +134,11 @@ public sealed class EvidenceChunkerTests
}
[Trait("Category", TestCategories.Unit)]
[Fact]
[Fact]
public async Task ReassembleAsync_ShouldThrow_WhenChunkCorrupted()
{
// Arrange
var evidence = new byte[100];
Random.Shared.NextBytes(evidence);
var evidence = CreateDeterministicBytes(100, 5);
const string contentType = "application/octet-stream";
var chunked = await _chunker.ChunkAsync(evidence, contentType);
@@ -161,24 +157,23 @@ public sealed class EvidenceChunkerTests
}
[Trait("Category", TestCategories.Unit)]
[Fact]
[Fact]
public void VerifyChunk_ShouldReturnTrue_WhenChunkValid()
{
// Arrange
var data = new byte[32];
Random.Shared.NextBytes(data);
var data = CreateDeterministicBytes(32, 6);
var hash = ComputeHash(data);
var chunk = new EvidenceChunk
{
ChunkId = Guid.NewGuid(),
ChunkId = CreateGuid(6),
ProofRoot = "sha256:test",
ChunkIndex = 0,
ChunkHash = hash,
Blob = data,
BlobSize = data.Length,
ContentType = "application/octet-stream",
CreatedAt = DateTimeOffset.UtcNow
CreatedAt = FixedNow
};
// Act & Assert
@@ -186,20 +181,20 @@ public sealed class EvidenceChunkerTests
}
[Trait("Category", TestCategories.Unit)]
[Fact]
[Fact]
public void VerifyChunk_ShouldReturnFalse_WhenHashMismatch()
{
// Arrange
var chunk = new EvidenceChunk
{
ChunkId = Guid.NewGuid(),
ChunkId = CreateGuid(7),
ProofRoot = "sha256:test",
ChunkIndex = 0,
ChunkHash = "sha256:wrong_hash",
Blob = new byte[32],
BlobSize = 32,
ContentType = "application/octet-stream",
CreatedAt = DateTimeOffset.UtcNow
CreatedAt = FixedNow
};
// Act & Assert
@@ -207,7 +202,7 @@ public sealed class EvidenceChunkerTests
}
[Trait("Category", TestCategories.Unit)]
[Fact]
[Fact]
public void ComputeMerkleRoot_ShouldReturnSameResult_ForSameInput()
{
// Arrange
@@ -223,7 +218,7 @@ public sealed class EvidenceChunkerTests
}
[Trait("Category", TestCategories.Unit)]
[Fact]
[Fact]
public void ComputeMerkleRoot_ShouldHandleSingleHash()
{
// Arrange
@@ -237,7 +232,7 @@ public sealed class EvidenceChunkerTests
}
[Trait("Category", TestCategories.Unit)]
[Fact]
[Fact]
public void ComputeMerkleRoot_ShouldHandleOddNumberOfHashes()
{
// Arrange
@@ -252,12 +247,11 @@ public sealed class EvidenceChunkerTests
}
[Trait("Category", TestCategories.Unit)]
[Fact]
[Fact]
public async Task ChunkStreamAsync_ShouldYieldChunksInOrder()
{
// Arrange
var evidence = new byte[200];
Random.Shared.NextBytes(evidence);
var evidence = CreateDeterministicBytes(200, 8);
using var stream = new MemoryStream(evidence);
const string contentType = "application/octet-stream";
@@ -277,15 +271,14 @@ public sealed class EvidenceChunkerTests
}
[Trait("Category", TestCategories.Unit)]
[Fact]
[Fact]
public async Task Roundtrip_ShouldPreserveDataIntegrity()
{
// Arrange - use realistic chunk size
var options = new ProvcacheOptions { ChunkSize = 1024 };
var chunker = new EvidenceChunker(options);
var original = new byte[5000]; // ~5 chunks
Random.Shared.NextBytes(original);
var original = CreateDeterministicBytes(5000, 9); // ~5 chunks
const string contentType = "application/octet-stream";
// Act
@@ -302,4 +295,17 @@ public sealed class EvidenceChunkerTests
var hash = System.Security.Cryptography.SHA256.HashData(data);
return $"sha256:{Convert.ToHexStringLower(hash)}";
}
private static byte[] CreateDeterministicBytes(int length, int seed)
{
var random = new DeterministicRandom(seed);
var data = new byte[length];
random.NextBytes(data);
return data;
}
private static Guid CreateGuid(int seed)
{
return new DeterministicRandom(seed).NextGuid();
}
}