feat(config-db): secured-write TryMarkExpiredAsync CAS + CountAsync (arch-review S2/P3)
Claude-Session: https://claude.ai/code/session_01MtdgwpEeCUn6cUA5f1LMPj
This commit is contained in:
+55
@@ -109,6 +109,61 @@ public class SecuredWriteRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
Assert.Contains(all, p => p.Id == executedId);
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public async Task TryMarkExpiredAsync_PendingRow_FlipsToExpired_Once()
|
||||
{
|
||||
Skip.IfNot(_fixture.Available, _fixture.SkipReason);
|
||||
|
||||
var siteId = NewSiteId();
|
||||
await using var context = CreateContext();
|
||||
var repo = new SecuredWriteRepository(context);
|
||||
|
||||
var id = await repo.AddAsync(NewRow(siteId, status: "Pending"));
|
||||
|
||||
Assert.True(await repo.TryMarkExpiredAsync(id, DateTime.UtcNow));
|
||||
// CAS: a second caller loses because the row is no longer Pending.
|
||||
Assert.False(await repo.TryMarkExpiredAsync(id, DateTime.UtcNow));
|
||||
|
||||
await using var readContext = CreateContext();
|
||||
var row = await new SecuredWriteRepository(readContext).GetAsync(id);
|
||||
Assert.NotNull(row);
|
||||
Assert.Equal("Expired", row!.Status);
|
||||
Assert.NotNull(row.DecidedAtUtc);
|
||||
Assert.Null(row.VerifierUser); // system decision, no verifier
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public async Task TryMarkExpiredAsync_DecidedRow_ReturnsFalse()
|
||||
{
|
||||
Skip.IfNot(_fixture.Available, _fixture.SkipReason);
|
||||
|
||||
var siteId = NewSiteId();
|
||||
await using var context = CreateContext();
|
||||
var repo = new SecuredWriteRepository(context);
|
||||
|
||||
var id = await repo.AddAsync(NewRow(siteId, status: "Pending"));
|
||||
Assert.True(await repo.TryMarkApprovedAsync(id, "ver.bob", null, DateTime.UtcNow));
|
||||
|
||||
// Already Approved -> the conditional WHERE Status='Pending' matches no row.
|
||||
Assert.False(await repo.TryMarkExpiredAsync(id, DateTime.UtcNow));
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public async Task CountAsync_FiltersLikeQueryAsync()
|
||||
{
|
||||
Skip.IfNot(_fixture.Available, _fixture.SkipReason);
|
||||
|
||||
var siteId = NewSiteId();
|
||||
await using var context = CreateContext();
|
||||
var repo = new SecuredWriteRepository(context);
|
||||
|
||||
await repo.AddAsync(NewRow(siteId, status: "Pending"));
|
||||
await repo.AddAsync(NewRow(siteId, status: "Pending"));
|
||||
|
||||
Assert.Equal(2, await repo.CountAsync(status: "Pending", siteId: siteId));
|
||||
Assert.Equal(0, await repo.CountAsync(status: "Executed", siteId: siteId));
|
||||
}
|
||||
|
||||
// --- helpers ------------------------------------------------------------
|
||||
|
||||
private ScadaBridgeDbContext CreateContext()
|
||||
|
||||
Reference in New Issue
Block a user