Refactor code structure and optimize performance across multiple modules
This commit is contained in:
@@ -18,7 +18,8 @@ public class EvidenceRecordTests
|
||||
|
||||
#region ComputeEvidenceId
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ComputeEvidenceId_ValidInputs_ReturnsSha256Prefixed()
|
||||
{
|
||||
var subjectId = "sha256:abc123";
|
||||
@@ -34,7 +35,8 @@ public class EvidenceRecordTests
|
||||
Assert.Equal(71, evidenceId.Length); // "sha256:" + 64 hex chars
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ComputeEvidenceId_SameInputs_ReturnsSameId()
|
||||
{
|
||||
var subjectId = "sha256:abc123";
|
||||
@@ -46,7 +48,8 @@ public class EvidenceRecordTests
|
||||
Assert.Equal(id1, id2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ComputeEvidenceId_DifferentSubjects_ReturnsDifferentIds()
|
||||
{
|
||||
var payload = Encoding.UTF8.GetBytes("""{"vulnerability":"CVE-2021-44228"}""");
|
||||
@@ -57,7 +60,8 @@ public class EvidenceRecordTests
|
||||
Assert.NotEqual(id1, id2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ComputeEvidenceId_DifferentTypes_ReturnsDifferentIds()
|
||||
{
|
||||
var subjectId = "sha256:abc123";
|
||||
@@ -69,7 +73,8 @@ public class EvidenceRecordTests
|
||||
Assert.NotEqual(id1, id2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ComputeEvidenceId_DifferentPayloads_ReturnsDifferentIds()
|
||||
{
|
||||
var subjectId = "sha256:abc123";
|
||||
@@ -82,7 +87,8 @@ public class EvidenceRecordTests
|
||||
Assert.NotEqual(id1, id2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ComputeEvidenceId_DifferentProvenance_ReturnsDifferentIds()
|
||||
{
|
||||
var subjectId = "sha256:abc123";
|
||||
@@ -108,7 +114,8 @@ public class EvidenceRecordTests
|
||||
Assert.NotEqual(id1, id2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ComputeEvidenceId_NullSubject_ThrowsArgumentException()
|
||||
{
|
||||
var payload = Encoding.UTF8.GetBytes("""{"data":"test"}""");
|
||||
@@ -116,7 +123,8 @@ public class EvidenceRecordTests
|
||||
EvidenceRecord.ComputeEvidenceId(null!, EvidenceType.Scan, payload, TestProvenance));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ComputeEvidenceId_EmptySubject_ThrowsArgumentException()
|
||||
{
|
||||
var payload = Encoding.UTF8.GetBytes("""{"data":"test"}""");
|
||||
@@ -124,7 +132,8 @@ public class EvidenceRecordTests
|
||||
EvidenceRecord.ComputeEvidenceId("", EvidenceType.Scan, payload, TestProvenance));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ComputeEvidenceId_NullProvenance_ThrowsArgumentNullException()
|
||||
{
|
||||
var payload = Encoding.UTF8.GetBytes("""{"data":"test"}""");
|
||||
@@ -136,7 +145,8 @@ public class EvidenceRecordTests
|
||||
|
||||
#region Create Factory Method
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Create_ValidInputs_ReturnsRecordWithComputedId()
|
||||
{
|
||||
var subjectId = "sha256:abc123";
|
||||
@@ -158,7 +168,8 @@ public class EvidenceRecordTests
|
||||
Assert.Null(record.ExternalPayloadCid);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Create_WithSignatures_IncludesSignatures()
|
||||
{
|
||||
var subjectId = "sha256:abc123";
|
||||
@@ -184,7 +195,8 @@ public class EvidenceRecordTests
|
||||
Assert.Equal("key-123", record.Signatures[0].SignerId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Create_WithExternalCid_IncludesCid()
|
||||
{
|
||||
var subjectId = "sha256:abc123";
|
||||
@@ -198,6 +210,7 @@ public class EvidenceRecordTests
|
||||
"reachability/v1",
|
||||
externalPayloadCid: "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi");
|
||||
|
||||
using StellaOps.TestKit;
|
||||
Assert.Equal("bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi", record.ExternalPayloadCid);
|
||||
}
|
||||
|
||||
@@ -205,7 +218,8 @@ public class EvidenceRecordTests
|
||||
|
||||
#region VerifyIntegrity
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void VerifyIntegrity_ValidRecord_ReturnsTrue()
|
||||
{
|
||||
var record = EvidenceRecord.Create(
|
||||
@@ -218,7 +232,8 @@ public class EvidenceRecordTests
|
||||
Assert.True(record.VerifyIntegrity());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void VerifyIntegrity_TamperedPayload_ReturnsFalse()
|
||||
{
|
||||
var originalPayload = Encoding.UTF8.GetBytes("""{"vulnerability":"CVE-2021-44228"}""");
|
||||
@@ -237,7 +252,8 @@ public class EvidenceRecordTests
|
||||
Assert.False(tampered.VerifyIntegrity());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void VerifyIntegrity_TamperedSubject_ReturnsFalse()
|
||||
{
|
||||
var record = EvidenceRecord.Create(
|
||||
@@ -256,7 +272,8 @@ public class EvidenceRecordTests
|
||||
|
||||
#region Determinism
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Create_SameInputs_ProducesSameEvidenceId()
|
||||
{
|
||||
var subjectId = "sha256:abc123";
|
||||
@@ -271,7 +288,8 @@ public class EvidenceRecordTests
|
||||
Assert.Single(ids);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void ComputeEvidenceId_EmptyPayload_Works()
|
||||
{
|
||||
var id = EvidenceRecord.ComputeEvidenceId(
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Immutable;
|
||||
using StellaOps.Evidence.Core;
|
||||
using StellaOps.Evidence.Core.Adapters;
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Evidence.Core.Tests;
|
||||
|
||||
public sealed class ExceptionApplicationAdapterTests
|
||||
@@ -24,7 +25,8 @@ public sealed class ExceptionApplicationAdapterTests
|
||||
};
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void CanConvert_WithValidApplication_ReturnsTrue()
|
||||
{
|
||||
var application = CreateValidApplication();
|
||||
@@ -34,7 +36,8 @@ public sealed class ExceptionApplicationAdapterTests
|
||||
Assert.True(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void CanConvert_WithNullApplication_ReturnsFalse()
|
||||
{
|
||||
var result = _adapter.CanConvert(null!);
|
||||
@@ -42,7 +45,8 @@ public sealed class ExceptionApplicationAdapterTests
|
||||
Assert.False(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void CanConvert_WithEmptyExceptionId_ReturnsFalse()
|
||||
{
|
||||
var application = CreateValidApplication() with { ExceptionId = "" };
|
||||
@@ -52,7 +56,8 @@ public sealed class ExceptionApplicationAdapterTests
|
||||
Assert.False(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void CanConvert_WithEmptyFindingId_ReturnsFalse()
|
||||
{
|
||||
var application = CreateValidApplication() with { FindingId = "" };
|
||||
@@ -62,7 +67,8 @@ public sealed class ExceptionApplicationAdapterTests
|
||||
Assert.False(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_CreatesSingleRecord()
|
||||
{
|
||||
var application = CreateValidApplication();
|
||||
@@ -72,7 +78,8 @@ public sealed class ExceptionApplicationAdapterTests
|
||||
Assert.Single(results);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_RecordHasExceptionType()
|
||||
{
|
||||
var application = CreateValidApplication();
|
||||
@@ -82,7 +89,8 @@ public sealed class ExceptionApplicationAdapterTests
|
||||
Assert.Equal(EvidenceType.Exception, results[0].EvidenceType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_RecordHasCorrectSubjectNodeId()
|
||||
{
|
||||
var application = CreateValidApplication();
|
||||
@@ -92,7 +100,8 @@ public sealed class ExceptionApplicationAdapterTests
|
||||
Assert.Equal(_subjectNodeId, results[0].SubjectNodeId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_RecordHasNonEmptyPayload()
|
||||
{
|
||||
var application = CreateValidApplication();
|
||||
@@ -102,7 +111,8 @@ public sealed class ExceptionApplicationAdapterTests
|
||||
Assert.False(results[0].Payload.IsEmpty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_RecordHasPayloadSchemaVersion()
|
||||
{
|
||||
var application = CreateValidApplication();
|
||||
@@ -112,7 +122,8 @@ public sealed class ExceptionApplicationAdapterTests
|
||||
Assert.Equal("1.0.0", results[0].PayloadSchemaVersion);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_RecordHasEmptySignatures()
|
||||
{
|
||||
var application = CreateValidApplication();
|
||||
@@ -122,7 +133,8 @@ public sealed class ExceptionApplicationAdapterTests
|
||||
Assert.Empty(results[0].Signatures);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_UsesProvidedProvenance()
|
||||
{
|
||||
var application = CreateValidApplication();
|
||||
@@ -133,7 +145,8 @@ public sealed class ExceptionApplicationAdapterTests
|
||||
Assert.Equal(_provenance.GeneratorVersion, results[0].Provenance.GeneratorVersion);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_RecordHasUniqueEvidenceId()
|
||||
{
|
||||
var application = CreateValidApplication();
|
||||
@@ -144,7 +157,8 @@ public sealed class ExceptionApplicationAdapterTests
|
||||
Assert.NotEmpty(results[0].EvidenceId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_WithNullSubjectNodeId_ThrowsArgumentNullException()
|
||||
{
|
||||
var application = CreateValidApplication();
|
||||
@@ -153,7 +167,8 @@ public sealed class ExceptionApplicationAdapterTests
|
||||
_adapter.Convert(application, null!, _provenance));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_WithEmptySubjectNodeId_ThrowsArgumentException()
|
||||
{
|
||||
var application = CreateValidApplication();
|
||||
@@ -162,7 +177,8 @@ public sealed class ExceptionApplicationAdapterTests
|
||||
_adapter.Convert(application, "", _provenance));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_WithNullProvenance_ThrowsArgumentNullException()
|
||||
{
|
||||
var application = CreateValidApplication();
|
||||
@@ -171,7 +187,8 @@ public sealed class ExceptionApplicationAdapterTests
|
||||
_adapter.Convert(application, _subjectNodeId, null!));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_WithVulnerabilityId_IncludesInPayload()
|
||||
{
|
||||
var application = CreateValidApplication() with { VulnerabilityId = "CVE-2024-9999" };
|
||||
@@ -181,7 +198,8 @@ public sealed class ExceptionApplicationAdapterTests
|
||||
Assert.False(results[0].Payload.IsEmpty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_WithEvaluationRunId_IncludesInPayload()
|
||||
{
|
||||
var runId = Guid.NewGuid();
|
||||
@@ -192,7 +210,8 @@ public sealed class ExceptionApplicationAdapterTests
|
||||
Assert.False(results[0].Payload.IsEmpty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_WithPolicyBundleDigest_IncludesInPayload()
|
||||
{
|
||||
var application = CreateValidApplication() with { PolicyBundleDigest = "sha256:policy123" };
|
||||
@@ -202,7 +221,8 @@ public sealed class ExceptionApplicationAdapterTests
|
||||
Assert.False(results[0].Payload.IsEmpty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_WithMetadata_IncludesInPayload()
|
||||
{
|
||||
var metadata = ImmutableDictionary<string, string>.Empty
|
||||
@@ -216,7 +236,8 @@ public sealed class ExceptionApplicationAdapterTests
|
||||
Assert.False(results[0].Payload.IsEmpty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_DifferentApplications_ProduceDifferentEvidenceIds()
|
||||
{
|
||||
var app1 = CreateValidApplication() with { ExceptionId = "exc-001" };
|
||||
@@ -228,7 +249,8 @@ public sealed class ExceptionApplicationAdapterTests
|
||||
Assert.NotEqual(results1[0].EvidenceId, results2[0].EvidenceId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_SameApplicationTwice_ProducesSameEvidenceId()
|
||||
{
|
||||
var application = CreateValidApplication();
|
||||
@@ -239,7 +261,8 @@ public sealed class ExceptionApplicationAdapterTests
|
||||
Assert.Equal(results1[0].EvidenceId, results2[0].EvidenceId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_AllStatusTransitions_Supported()
|
||||
{
|
||||
var transitions = new[]
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Text;
|
||||
using Xunit;
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Evidence.Core.Tests;
|
||||
|
||||
/// <summary>
|
||||
@@ -28,7 +29,8 @@ public class InMemoryEvidenceStoreTests
|
||||
|
||||
#region StoreAsync
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task StoreAsync_ValidEvidence_ReturnsEvidenceId()
|
||||
{
|
||||
var evidence = CreateTestEvidence("sha256:subject1");
|
||||
@@ -39,7 +41,8 @@ public class InMemoryEvidenceStoreTests
|
||||
Assert.Equal(1, _store.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task StoreAsync_DuplicateEvidence_IsIdempotent()
|
||||
{
|
||||
var evidence = CreateTestEvidence("sha256:subject1");
|
||||
@@ -50,7 +53,8 @@ public class InMemoryEvidenceStoreTests
|
||||
Assert.Equal(1, _store.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task StoreAsync_NullEvidence_ThrowsArgumentNullException()
|
||||
{
|
||||
await Assert.ThrowsAsync<ArgumentNullException>(() => _store.StoreAsync(null!));
|
||||
@@ -60,7 +64,8 @@ public class InMemoryEvidenceStoreTests
|
||||
|
||||
#region StoreBatchAsync
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task StoreBatchAsync_MultipleRecords_StoresAll()
|
||||
{
|
||||
var evidence1 = CreateTestEvidence("sha256:subject1");
|
||||
@@ -73,7 +78,8 @@ public class InMemoryEvidenceStoreTests
|
||||
Assert.Equal(3, _store.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task StoreBatchAsync_WithDuplicates_SkipsDuplicates()
|
||||
{
|
||||
var evidence1 = CreateTestEvidence("sha256:subject1");
|
||||
@@ -86,7 +92,8 @@ public class InMemoryEvidenceStoreTests
|
||||
Assert.Equal(2, _store.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task StoreBatchAsync_EmptyList_ReturnsZero()
|
||||
{
|
||||
var count = await _store.StoreBatchAsync([]);
|
||||
@@ -99,7 +106,8 @@ public class InMemoryEvidenceStoreTests
|
||||
|
||||
#region GetByIdAsync
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task GetByIdAsync_ExistingEvidence_ReturnsEvidence()
|
||||
{
|
||||
var evidence = CreateTestEvidence("sha256:subject1");
|
||||
@@ -112,7 +120,8 @@ public class InMemoryEvidenceStoreTests
|
||||
Assert.Equal(evidence.SubjectNodeId, result.SubjectNodeId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task GetByIdAsync_NonExistingEvidence_ReturnsNull()
|
||||
{
|
||||
var result = await _store.GetByIdAsync("sha256:nonexistent");
|
||||
@@ -120,13 +129,15 @@ public class InMemoryEvidenceStoreTests
|
||||
Assert.Null(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task GetByIdAsync_NullId_ThrowsArgumentException()
|
||||
{
|
||||
await Assert.ThrowsAnyAsync<ArgumentException>(() => _store.GetByIdAsync(null!));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task GetByIdAsync_EmptyId_ThrowsArgumentException()
|
||||
{
|
||||
await Assert.ThrowsAnyAsync<ArgumentException>(() => _store.GetByIdAsync(""));
|
||||
@@ -136,7 +147,8 @@ public class InMemoryEvidenceStoreTests
|
||||
|
||||
#region GetBySubjectAsync
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task GetBySubjectAsync_ExistingSubject_ReturnsAllEvidence()
|
||||
{
|
||||
var subjectId = "sha256:subject1";
|
||||
@@ -151,7 +163,8 @@ public class InMemoryEvidenceStoreTests
|
||||
Assert.Equal(2, results.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task GetBySubjectAsync_WithTypeFilter_ReturnsFilteredResults()
|
||||
{
|
||||
var subjectId = "sha256:subject1";
|
||||
@@ -167,7 +180,8 @@ public class InMemoryEvidenceStoreTests
|
||||
Assert.Equal(EvidenceType.Scan, results[0].EvidenceType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task GetBySubjectAsync_NonExistingSubject_ReturnsEmptyList()
|
||||
{
|
||||
var results = await _store.GetBySubjectAsync("sha256:nonexistent");
|
||||
@@ -179,7 +193,8 @@ public class InMemoryEvidenceStoreTests
|
||||
|
||||
#region GetByTypeAsync
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task GetByTypeAsync_ExistingType_ReturnsMatchingEvidence()
|
||||
{
|
||||
await _store.StoreAsync(CreateTestEvidence("sha256:sub1", EvidenceType.Scan));
|
||||
@@ -192,7 +207,8 @@ public class InMemoryEvidenceStoreTests
|
||||
Assert.All(results, r => Assert.Equal(EvidenceType.Scan, r.EvidenceType));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task GetByTypeAsync_WithLimit_RespectsLimit()
|
||||
{
|
||||
for (int i = 0; i < 10; i++)
|
||||
@@ -205,7 +221,8 @@ public class InMemoryEvidenceStoreTests
|
||||
Assert.Equal(5, results.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task GetByTypeAsync_NonExistingType_ReturnsEmptyList()
|
||||
{
|
||||
await _store.StoreAsync(CreateTestEvidence("sha256:sub1", EvidenceType.Scan));
|
||||
@@ -219,7 +236,8 @@ public class InMemoryEvidenceStoreTests
|
||||
|
||||
#region ExistsAsync
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task ExistsAsync_ExistingEvidenceForType_ReturnsTrue()
|
||||
{
|
||||
var subjectId = "sha256:subject1";
|
||||
@@ -230,7 +248,8 @@ public class InMemoryEvidenceStoreTests
|
||||
Assert.True(exists);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task ExistsAsync_DifferentType_ReturnsFalse()
|
||||
{
|
||||
var subjectId = "sha256:subject1";
|
||||
@@ -241,7 +260,8 @@ public class InMemoryEvidenceStoreTests
|
||||
Assert.False(exists);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task ExistsAsync_NonExistingSubject_ReturnsFalse()
|
||||
{
|
||||
var exists = await _store.ExistsAsync("sha256:nonexistent", EvidenceType.Scan);
|
||||
@@ -253,7 +273,8 @@ public class InMemoryEvidenceStoreTests
|
||||
|
||||
#region DeleteAsync
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task DeleteAsync_ExistingEvidence_ReturnsTrue()
|
||||
{
|
||||
var evidence = CreateTestEvidence("sha256:subject1");
|
||||
@@ -265,7 +286,8 @@ public class InMemoryEvidenceStoreTests
|
||||
Assert.Equal(0, _store.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task DeleteAsync_NonExistingEvidence_ReturnsFalse()
|
||||
{
|
||||
var deleted = await _store.DeleteAsync("sha256:nonexistent");
|
||||
@@ -273,7 +295,8 @@ public class InMemoryEvidenceStoreTests
|
||||
Assert.False(deleted);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task DeleteAsync_RemovedEvidence_NotRetrievable()
|
||||
{
|
||||
var evidence = CreateTestEvidence("sha256:subject1");
|
||||
@@ -289,7 +312,8 @@ public class InMemoryEvidenceStoreTests
|
||||
|
||||
#region CountBySubjectAsync
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task CountBySubjectAsync_MultipleEvidence_ReturnsCorrectCount()
|
||||
{
|
||||
var subjectId = "sha256:subject1";
|
||||
@@ -302,7 +326,8 @@ public class InMemoryEvidenceStoreTests
|
||||
Assert.Equal(3, count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task CountBySubjectAsync_NoEvidence_ReturnsZero()
|
||||
{
|
||||
var count = await _store.CountBySubjectAsync("sha256:nonexistent");
|
||||
@@ -314,7 +339,8 @@ public class InMemoryEvidenceStoreTests
|
||||
|
||||
#region Clear
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task Clear_RemovesAllEvidence()
|
||||
{
|
||||
await _store.StoreAsync(CreateTestEvidence("sha256:sub1"));
|
||||
@@ -329,7 +355,8 @@ public class InMemoryEvidenceStoreTests
|
||||
|
||||
#region Cancellation
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task StoreAsync_CancelledToken_ThrowsOperationCancelledException()
|
||||
{
|
||||
var cts = new CancellationTokenSource();
|
||||
@@ -341,7 +368,8 @@ public class InMemoryEvidenceStoreTests
|
||||
_store.StoreAsync(evidence, cts.Token));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public async Task GetByIdAsync_CancelledToken_ThrowsOperationCancelledException()
|
||||
{
|
||||
var cts = new CancellationTokenSource();
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Immutable;
|
||||
using StellaOps.Evidence.Core;
|
||||
using StellaOps.Evidence.Core.Adapters;
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Evidence.Core.Tests;
|
||||
|
||||
public sealed class ProofSegmentAdapterTests
|
||||
@@ -24,7 +25,8 @@ public sealed class ProofSegmentAdapterTests
|
||||
};
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void CanConvert_WithValidSegment_ReturnsTrue()
|
||||
{
|
||||
var segment = CreateValidSegment();
|
||||
@@ -34,7 +36,8 @@ public sealed class ProofSegmentAdapterTests
|
||||
Assert.True(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void CanConvert_WithNullSegment_ReturnsFalse()
|
||||
{
|
||||
var result = _adapter.CanConvert(null!);
|
||||
@@ -42,7 +45,8 @@ public sealed class ProofSegmentAdapterTests
|
||||
Assert.False(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void CanConvert_WithEmptySegmentId_ReturnsFalse()
|
||||
{
|
||||
var segment = CreateValidSegment() with { SegmentId = "" };
|
||||
@@ -52,7 +56,8 @@ public sealed class ProofSegmentAdapterTests
|
||||
Assert.False(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void CanConvert_WithEmptyInputHash_ReturnsFalse()
|
||||
{
|
||||
var segment = CreateValidSegment() with { InputHash = "" };
|
||||
@@ -62,7 +67,8 @@ public sealed class ProofSegmentAdapterTests
|
||||
Assert.False(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_CreatesSingleRecord()
|
||||
{
|
||||
var segment = CreateValidSegment();
|
||||
@@ -72,7 +78,8 @@ public sealed class ProofSegmentAdapterTests
|
||||
Assert.Single(results);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_RecordHasCorrectSubjectNodeId()
|
||||
{
|
||||
var segment = CreateValidSegment();
|
||||
@@ -82,7 +89,8 @@ public sealed class ProofSegmentAdapterTests
|
||||
Assert.Equal(_subjectNodeId, results[0].SubjectNodeId);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Theory]
|
||||
[InlineData("SbomSlice", EvidenceType.Artifact)]
|
||||
[InlineData("Match", EvidenceType.Scan)]
|
||||
[InlineData("Reachability", EvidenceType.Reachability)]
|
||||
@@ -98,7 +106,8 @@ public sealed class ProofSegmentAdapterTests
|
||||
Assert.Equal(expectedType, results[0].EvidenceType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_UnknownSegmentType_DefaultsToCustomType()
|
||||
{
|
||||
var segment = CreateValidSegment() with { SegmentType = "UnknownType" };
|
||||
@@ -108,7 +117,8 @@ public sealed class ProofSegmentAdapterTests
|
||||
Assert.Equal(EvidenceType.Custom, results[0].EvidenceType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_RecordHasNonEmptyPayload()
|
||||
{
|
||||
var segment = CreateValidSegment();
|
||||
@@ -118,7 +128,8 @@ public sealed class ProofSegmentAdapterTests
|
||||
Assert.False(results[0].Payload.IsEmpty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_RecordHasPayloadSchemaVersion()
|
||||
{
|
||||
var segment = CreateValidSegment();
|
||||
@@ -128,7 +139,8 @@ public sealed class ProofSegmentAdapterTests
|
||||
Assert.Equal("proof-segment/v1", results[0].PayloadSchemaVersion);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_RecordHasEmptySignatures()
|
||||
{
|
||||
var segment = CreateValidSegment();
|
||||
@@ -138,7 +150,8 @@ public sealed class ProofSegmentAdapterTests
|
||||
Assert.Empty(results[0].Signatures);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_UsesProvidedProvenance()
|
||||
{
|
||||
var segment = CreateValidSegment();
|
||||
@@ -149,7 +162,8 @@ public sealed class ProofSegmentAdapterTests
|
||||
Assert.Equal(_provenance.GeneratorVersion, results[0].Provenance.GeneratorVersion);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_RecordHasUniqueEvidenceId()
|
||||
{
|
||||
var segment = CreateValidSegment();
|
||||
@@ -160,7 +174,8 @@ public sealed class ProofSegmentAdapterTests
|
||||
Assert.NotEmpty(results[0].EvidenceId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_WithNullSubjectNodeId_ThrowsArgumentNullException()
|
||||
{
|
||||
var segment = CreateValidSegment();
|
||||
@@ -169,7 +184,8 @@ public sealed class ProofSegmentAdapterTests
|
||||
_adapter.Convert(segment, null!, _provenance));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_WithNullProvenance_ThrowsArgumentNullException()
|
||||
{
|
||||
var segment = CreateValidSegment();
|
||||
@@ -178,7 +194,8 @@ public sealed class ProofSegmentAdapterTests
|
||||
_adapter.Convert(segment, _subjectNodeId, null!));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_DifferentSegments_ProduceDifferentEvidenceIds()
|
||||
{
|
||||
var segment1 = CreateValidSegment() with { SegmentId = "seg-001" };
|
||||
@@ -190,7 +207,8 @@ public sealed class ProofSegmentAdapterTests
|
||||
Assert.NotEqual(results1[0].EvidenceId, results2[0].EvidenceId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_SameSegmentTwice_ProducesSameEvidenceId()
|
||||
{
|
||||
var segment = CreateValidSegment();
|
||||
@@ -201,7 +219,8 @@ public sealed class ProofSegmentAdapterTests
|
||||
Assert.Equal(results1[0].EvidenceId, results2[0].EvidenceId);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Theory]
|
||||
[InlineData("Pending")]
|
||||
[InlineData("Verified")]
|
||||
[InlineData("Partial")]
|
||||
@@ -216,7 +235,8 @@ public sealed class ProofSegmentAdapterTests
|
||||
Assert.Single(results);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_WithToolInfo_IncludesInPayload()
|
||||
{
|
||||
var segment = CreateValidSegment() with
|
||||
@@ -230,7 +250,8 @@ public sealed class ProofSegmentAdapterTests
|
||||
Assert.False(results[0].Payload.IsEmpty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_WithPrevSegmentHash_IncludesInPayload()
|
||||
{
|
||||
var segment = CreateValidSegment() with { PrevSegmentHash = "sha256:prevhash" };
|
||||
@@ -240,7 +261,8 @@ public sealed class ProofSegmentAdapterTests
|
||||
Assert.False(results[0].Payload.IsEmpty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_WithSpineId_IncludesInPayload()
|
||||
{
|
||||
var segment = CreateValidSegment() with { SpineId = "spine-001" };
|
||||
|
||||
@@ -24,5 +24,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\StellaOps.Evidence.Core\StellaOps.Evidence.Core.csproj" />
|
||||
<ProjectReference Include="../StellaOps.TestKit/StellaOps.TestKit.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Immutable;
|
||||
using StellaOps.Evidence.Core;
|
||||
using StellaOps.Evidence.Core.Adapters;
|
||||
|
||||
using StellaOps.TestKit;
|
||||
namespace StellaOps.Evidence.Core.Tests;
|
||||
|
||||
public sealed class VexObservationAdapterTests
|
||||
@@ -24,7 +25,8 @@ public sealed class VexObservationAdapterTests
|
||||
};
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void CanConvert_WithValidObservation_ReturnsTrue()
|
||||
{
|
||||
var observation = CreateValidObservation();
|
||||
@@ -34,7 +36,8 @@ public sealed class VexObservationAdapterTests
|
||||
Assert.True(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void CanConvert_WithNullObservation_ReturnsFalse()
|
||||
{
|
||||
var result = _adapter.CanConvert(null!);
|
||||
@@ -42,7 +45,8 @@ public sealed class VexObservationAdapterTests
|
||||
Assert.False(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void CanConvert_WithEmptyObservationId_ReturnsFalse()
|
||||
{
|
||||
var observation = CreateValidObservation() with { ObservationId = "" };
|
||||
@@ -52,7 +56,8 @@ public sealed class VexObservationAdapterTests
|
||||
Assert.False(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void CanConvert_WithEmptyProviderId_ReturnsFalse()
|
||||
{
|
||||
var observation = CreateValidObservation() with { ProviderId = "" };
|
||||
@@ -62,7 +67,8 @@ public sealed class VexObservationAdapterTests
|
||||
Assert.False(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_CreatesObservationLevelRecord()
|
||||
{
|
||||
var observation = CreateValidObservation();
|
||||
@@ -75,7 +81,8 @@ public sealed class VexObservationAdapterTests
|
||||
Assert.Equal(_subjectNodeId, observationRecord.SubjectNodeId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_CreatesStatementRecordsForEachStatement()
|
||||
{
|
||||
var statements = ImmutableArray.Create(
|
||||
@@ -100,7 +107,8 @@ public sealed class VexObservationAdapterTests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_WithSingleStatement_CreatesCorrectRecords()
|
||||
{
|
||||
var observation = CreateValidObservation();
|
||||
@@ -111,7 +119,8 @@ public sealed class VexObservationAdapterTests
|
||||
Assert.Equal(2, results.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_WithEmptyStatements_CreatesOnlyObservationRecord()
|
||||
{
|
||||
var observation = CreateValidObservation() with { Statements = [] };
|
||||
@@ -122,7 +131,8 @@ public sealed class VexObservationAdapterTests
|
||||
Assert.Equal(EvidenceType.Provenance, results[0].EvidenceType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_WithSignature_IncludesSignatureInRecords()
|
||||
{
|
||||
var signature = new VexObservationSignatureInput
|
||||
@@ -147,7 +157,8 @@ public sealed class VexObservationAdapterTests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_WithoutSignature_CreatesRecordsWithEmptySignatures()
|
||||
{
|
||||
var signature = new VexObservationSignatureInput
|
||||
@@ -169,7 +180,8 @@ public sealed class VexObservationAdapterTests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_UsesProvidedProvenance()
|
||||
{
|
||||
var observation = CreateValidObservation();
|
||||
@@ -183,7 +195,8 @@ public sealed class VexObservationAdapterTests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_WithNullSubjectNodeId_ThrowsArgumentNullException()
|
||||
{
|
||||
var observation = CreateValidObservation();
|
||||
@@ -192,7 +205,8 @@ public sealed class VexObservationAdapterTests
|
||||
_adapter.Convert(observation, null!, _provenance));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_WithNullProvenance_ThrowsArgumentNullException()
|
||||
{
|
||||
var observation = CreateValidObservation();
|
||||
@@ -201,7 +215,8 @@ public sealed class VexObservationAdapterTests
|
||||
_adapter.Convert(observation, _subjectNodeId, null!));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_EachRecordHasUniqueEvidenceId()
|
||||
{
|
||||
var statements = ImmutableArray.Create(
|
||||
@@ -216,7 +231,8 @@ public sealed class VexObservationAdapterTests
|
||||
Assert.Equal(evidenceIds.Count, evidenceIds.Distinct().Count());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Category", TestCategories.Unit)]
|
||||
[Fact]
|
||||
public void Convert_RecordsHavePayloadSchemaVersion()
|
||||
{
|
||||
var observation = CreateValidObservation();
|
||||
|
||||
Reference in New Issue
Block a user