Files
git.stella-ops.org/src/JobEngine/StellaOps.PacksRegistry/StellaOps.PacksRegistry.Tests/PackServiceTests.cs

100 lines
3.7 KiB
C#

using StellaOps.PacksRegistry.Core.Services;
using StellaOps.PacksRegistry.Infrastructure.InMemory;
using StellaOps.PacksRegistry.Infrastructure.Verification;
using StellaOps.TestKit;
namespace StellaOps.PacksRegistry.Tests;
public sealed class PackServiceTests
{
private static byte[] SampleContent => System.Text.Encoding.UTF8.GetBytes("sample-pack-content");
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task Upload_persists_pack_with_digest()
{
var ct = CancellationToken.None;
var repo = new InMemoryPackRepository();
var verifier = new SimpleSignatureVerifier();
var service = new PackService(repo, verifier, new InMemoryAuditRepository(), null, TimeProvider.System);
var record = await service.UploadAsync(
name: "demo-pack",
version: "1.0.0",
tenantId: "tenant-1",
content: SampleContent,
signature: null,
provenanceUri: "https://example/manifest.json",
provenanceContent: null,
metadata: new Dictionary<string, string> { ["lang"] = "csharp" },
cancellationToken: ct);
Assert.Equal("demo-pack@1.0.0", record.PackId);
Assert.NotNull(record.Digest);
var listed = await service.ListAsync("tenant-1", ct);
Assert.Single(listed);
Assert.Equal(record.PackId, listed[0].PackId);
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task Upload_rejects_when_digest_mismatch()
{
var ct = CancellationToken.None;
var repo = new InMemoryPackRepository();
var verifier = new AlwaysFailSignatureVerifier();
var service = new PackService(repo, verifier, new InMemoryAuditRepository(), null, TimeProvider.System);
await Assert.ThrowsAsync<InvalidOperationException>(() =>
service.UploadAsync(
name: "demo-pack",
version: "1.0.0",
tenantId: "tenant-1",
content: SampleContent,
signature: "bogus",
provenanceUri: null,
provenanceContent: null,
metadata: null,
cancellationToken: ct));
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task Rotate_signature_updates_record_and_audits()
{
var ct = CancellationToken.None;
var repo = new InMemoryPackRepository();
var audit = new InMemoryAuditRepository();
var verifier = new SimpleSignatureVerifier();
var service = new PackService(repo, verifier, audit, null, TimeProvider.System);
var record = await service.UploadAsync(
name: "demo-pack",
version: "1.0.0",
tenantId: "tenant-1",
content: SampleContent,
signature: null,
provenanceUri: null,
provenanceContent: null,
metadata: null,
cancellationToken: ct);
var digest = record.Digest;
var newSignature = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(digest));
var rotated = await service.RotateSignatureAsync(record.PackId, record.TenantId, newSignature, cancellationToken: ct);
Assert.Equal(newSignature, rotated.Signature);
var auditEvents = await audit.ListAsync(record.TenantId, ct);
Assert.Contains(auditEvents, a => a.Event == "signature.rotated" && a.PackId == record.PackId);
}
private sealed class AlwaysFailSignatureVerifier : StellaOps.PacksRegistry.Core.Contracts.IPackSignatureVerifier
{
public Task<bool> VerifyAsync(byte[] content, string digest, string? signature, CancellationToken cancellationToken = default)
=> Task.FromResult(false);
}
}