Add property-based tests for SBOM/VEX document ordering and Unicode normalization determinism

- Implement `SbomVexOrderingDeterminismProperties` for testing component list and vulnerability metadata hash consistency.
- Create `UnicodeNormalizationDeterminismProperties` to validate NFC normalization and Unicode string handling.
- Add project file for `StellaOps.Testing.Determinism.Properties` with necessary dependencies.
- Introduce CI/CD template validation tests including YAML syntax checks and documentation content verification.
- Create validation script for CI/CD templates ensuring all required files and structures are present.
This commit is contained in:
StellaOps Bot
2025-12-26 15:17:15 +02:00
parent 7792749bb4
commit 907783f625
354 changed files with 79727 additions and 1346 deletions

View File

@@ -80,7 +80,7 @@ public class TemporalKeyVerificationTests : IDisposable
var beforeKeyAdded = _key2024AddedAt.AddDays(-30); // Dec 2023
// Act
var result = await _service.CheckKeyValidityAsync(anchor.Id, "key-2024", beforeKeyAdded);
var result = await _service.CheckKeyValidityAsync(anchor.AnchorId, "key-2024", beforeKeyAdded);
// Assert
result.IsValid.Should().BeFalse();
@@ -96,7 +96,7 @@ public class TemporalKeyVerificationTests : IDisposable
var duringActiveWindow = _key2024AddedAt.AddMonths(3); // April 2024
// Act
var result = await _service.CheckKeyValidityAsync(anchor.Id, "key-2024", duringActiveWindow);
var result = await _service.CheckKeyValidityAsync(anchor.AnchorId, "key-2024", duringActiveWindow);
// Assert
result.IsValid.Should().BeTrue();
@@ -112,7 +112,7 @@ public class TemporalKeyVerificationTests : IDisposable
var signedDuringOverlap = _key2024RevokedAt.AddDays(-30); // Dec 2024
// Act
var result = await _service.CheckKeyValidityAsync(anchor.Id, "key-2024", signedDuringOverlap);
var result = await _service.CheckKeyValidityAsync(anchor.AnchorId, "key-2024", signedDuringOverlap);
// Assert - key-2024 should be valid because signature was made before revocation
result.IsValid.Should().BeTrue();
@@ -127,7 +127,7 @@ public class TemporalKeyVerificationTests : IDisposable
var signedAfterRevocation = _key2024RevokedAt.AddDays(30); // Feb 2025
// Act
var result = await _service.CheckKeyValidityAsync(anchor.Id, "key-2024", signedAfterRevocation);
var result = await _service.CheckKeyValidityAsync(anchor.AnchorId, "key-2024", signedAfterRevocation);
// Assert - key-2024 should be invalid because signature was made after revocation
result.IsValid.Should().BeFalse();
@@ -143,7 +143,7 @@ public class TemporalKeyVerificationTests : IDisposable
var signedWithNewKey = _key2024RevokedAt.AddDays(30); // Feb 2025
// Act
var result = await _service.CheckKeyValidityAsync(anchor.Id, "key-2025", signedWithNewKey);
var result = await _service.CheckKeyValidityAsync(anchor.AnchorId, "key-2025", signedWithNewKey);
// Assert - key-2025 should be valid
result.IsValid.Should().BeTrue();
@@ -163,8 +163,8 @@ public class TemporalKeyVerificationTests : IDisposable
var duringOverlap = new DateTimeOffset(2024, 9, 15, 0, 0, 0, TimeSpan.Zero); // Sep 2024
// Act
var result2024 = await _service.CheckKeyValidityAsync(anchor.Id, "key-2024", duringOverlap);
var result2025 = await _service.CheckKeyValidityAsync(anchor.Id, "key-2025", duringOverlap);
var result2024 = await _service.CheckKeyValidityAsync(anchor.AnchorId, "key-2024", duringOverlap);
var result2025 = await _service.CheckKeyValidityAsync(anchor.AnchorId, "key-2025", duringOverlap);
// Assert - both keys should be valid during overlap
result2024.IsValid.Should().BeTrue();
@@ -181,7 +181,7 @@ public class TemporalKeyVerificationTests : IDisposable
var anchor = await CreateTestAnchorWithTimelineAsync();
// Act - at exact revocation time, key is already revoked
var result = await _service.CheckKeyValidityAsync(anchor.Id, "key-2024", _key2024RevokedAt);
var result = await _service.CheckKeyValidityAsync(anchor.AnchorId, "key-2024", _key2024RevokedAt);
// Assert - at revocation time, key should be considered revoked
result.IsValid.Should().BeFalse();
@@ -196,7 +196,7 @@ public class TemporalKeyVerificationTests : IDisposable
var justBeforeRevocation = _key2024RevokedAt.AddMilliseconds(-1);
// Act
var result = await _service.CheckKeyValidityAsync(anchor.Id, "key-2024", justBeforeRevocation);
var result = await _service.CheckKeyValidityAsync(anchor.AnchorId, "key-2024", justBeforeRevocation);
// Assert - key should still be valid
result.IsValid.Should().BeTrue();
@@ -216,7 +216,7 @@ public class TemporalKeyVerificationTests : IDisposable
var signedBeforeExpiry = expiryDate.AddDays(-30); // Feb 2025
// Act
var result = await _service.CheckKeyValidityAsync(anchor.Id, "expiring-key", signedBeforeExpiry);
var result = await _service.CheckKeyValidityAsync(anchor.AnchorId, "expiring-key", signedBeforeExpiry);
// Assert - should be valid because signed before expiry
result.IsValid.Should().BeTrue();
@@ -232,7 +232,7 @@ public class TemporalKeyVerificationTests : IDisposable
var signedAfterExpiry = expiryDate.AddDays(30); // April 2025
// Act
var result = await _service.CheckKeyValidityAsync(anchor.Id, "expiring-key", signedAfterExpiry);
var result = await _service.CheckKeyValidityAsync(anchor.AnchorId, "expiring-key", signedAfterExpiry);
// Assert - should be invalid because signed after expiry
result.IsValid.Should().BeFalse();
@@ -250,7 +250,7 @@ public class TemporalKeyVerificationTests : IDisposable
var anchor = await CreateTestAnchorWithTimelineAsync();
// Act
var result = await _service.CheckKeyValidityAsync(anchor.Id, "nonexistent-key", _currentTime);
var result = await _service.CheckKeyValidityAsync(anchor.AnchorId, "nonexistent-key", _currentTime);
// Assert
result.IsValid.Should().BeFalse();
@@ -281,9 +281,9 @@ public class TemporalKeyVerificationTests : IDisposable
var checkTime = new DateTimeOffset(2024, 9, 15, 10, 30, 45, TimeSpan.Zero);
// Act - call multiple times
var result1 = await _service.CheckKeyValidityAsync(anchor.Id, "key-2024", checkTime);
var result2 = await _service.CheckKeyValidityAsync(anchor.Id, "key-2024", checkTime);
var result3 = await _service.CheckKeyValidityAsync(anchor.Id, "key-2024", checkTime);
var result1 = await _service.CheckKeyValidityAsync(anchor.AnchorId, "key-2024", checkTime);
var result2 = await _service.CheckKeyValidityAsync(anchor.AnchorId, "key-2024", checkTime);
var result3 = await _service.CheckKeyValidityAsync(anchor.AnchorId, "key-2024", checkTime);
// Assert - all results should be identical
result1.Should().BeEquivalentTo(result2);
@@ -301,9 +301,9 @@ public class TemporalKeyVerificationTests : IDisposable
var jstTime = new DateTimeOffset(2024, 9, 15, 21, 0, 0, TimeSpan.FromHours(9));
// Act
var resultUtc = await _service.CheckKeyValidityAsync(anchor.Id, "key-2024", utcTime);
var resultPst = await _service.CheckKeyValidityAsync(anchor.Id, "key-2024", pstTime);
var resultJst = await _service.CheckKeyValidityAsync(anchor.Id, "key-2024", jstTime);
var resultUtc = await _service.CheckKeyValidityAsync(anchor.AnchorId, "key-2024", utcTime);
var resultPst = await _service.CheckKeyValidityAsync(anchor.AnchorId, "key-2024", pstTime);
var resultJst = await _service.CheckKeyValidityAsync(anchor.AnchorId, "key-2024", jstTime);
// Assert - all should return same result (same UTC instant)
resultUtc.IsValid.Should().Be(resultPst.IsValid);
@@ -320,7 +320,7 @@ public class TemporalKeyVerificationTests : IDisposable
{
var anchor = new TrustAnchorEntity
{
Id = Guid.NewGuid(),
AnchorId = Guid.NewGuid(),
PurlPattern = "pkg:npm/*",
AllowedKeyIds = ["key-2024", "key-2025"],
RevokedKeyIds = ["key-2024"],
@@ -333,30 +333,32 @@ public class TemporalKeyVerificationTests : IDisposable
{
new KeyHistoryEntity
{
Id = Guid.NewGuid(),
TrustAnchorId = anchor.Id,
HistoryId = Guid.NewGuid(),
AnchorId = anchor.AnchorId,
KeyId = "key-2024",
PublicKey = "-----BEGIN PUBLIC KEY-----\ntest-key-2024\n-----END PUBLIC KEY-----",
Algorithm = "Ed25519",
AddedAt = _key2024AddedAt,
RevokedAt = _key2024RevokedAt,
RevokeReason = "annual-rotation",
CreatedBy = "test-user"
CreatedAt = _key2024AddedAt
},
new KeyHistoryEntity
{
Id = Guid.NewGuid(),
TrustAnchorId = anchor.Id,
HistoryId = Guid.NewGuid(),
AnchorId = anchor.AnchorId,
KeyId = "key-2025",
PublicKey = "-----BEGIN PUBLIC KEY-----\ntest-key-2025\n-----END PUBLIC KEY-----",
Algorithm = "Ed25519",
AddedAt = _key2025AddedAt,
RevokedAt = null,
RevokeReason = null,
CreatedBy = "test-user"
CreatedAt = _key2025AddedAt
}
};
_dbContext.TrustAnchors.Add(anchor);
_dbContext.KeyHistories.AddRange(keyHistory);
_dbContext.KeyHistory.AddRange(keyHistory);
await _dbContext.SaveChangesAsync();
return anchor;
@@ -366,7 +368,7 @@ public class TemporalKeyVerificationTests : IDisposable
{
var anchor = new TrustAnchorEntity
{
Id = Guid.NewGuid(),
AnchorId = Guid.NewGuid(),
PurlPattern = "pkg:pypi/*",
AllowedKeyIds = ["expiring-key"],
RevokedKeyIds = [],
@@ -377,19 +379,20 @@ public class TemporalKeyVerificationTests : IDisposable
var keyHistory = new KeyHistoryEntity
{
Id = Guid.NewGuid(),
TrustAnchorId = anchor.Id,
HistoryId = Guid.NewGuid(),
AnchorId = anchor.AnchorId,
KeyId = "expiring-key",
PublicKey = "-----BEGIN PUBLIC KEY-----\ntest-expiring-key\n-----END PUBLIC KEY-----",
Algorithm = "Ed25519",
AddedAt = new DateTimeOffset(2025, 1, 1, 0, 0, 0, TimeSpan.Zero),
ExpiresAt = new DateTimeOffset(2025, 3, 1, 0, 0, 0, TimeSpan.Zero),
RevokedAt = null,
RevokeReason = null,
CreatedBy = "test-user"
CreatedAt = new DateTimeOffset(2025, 1, 1, 0, 0, 0, TimeSpan.Zero)
};
_dbContext.TrustAnchors.Add(anchor);
_dbContext.KeyHistories.Add(keyHistory);
_dbContext.KeyHistory.Add(keyHistory);
await _dbContext.SaveChangesAsync();
return anchor;
@@ -398,21 +401,4 @@ public class TemporalKeyVerificationTests : IDisposable
#endregion
}
/// <summary>
/// Fake time provider for testing temporal logic.
/// </summary>
public class FakeTimeProvider : TimeProvider
{
private DateTimeOffset _currentTime;
public FakeTimeProvider(DateTimeOffset startTime)
{
_currentTime = startTime;
}
public override DateTimeOffset GetUtcNow() => _currentTime;
public void SetTime(DateTimeOffset newTime) => _currentTime = newTime;
public void AdvanceBy(TimeSpan duration) => _currentTime += duration;
}
// Note: FakeTimeProvider is defined in KeyRotationServiceTests.cs