docs(tests): fix CommentChecker findings across tests/ — 13,392 → 0 (repo-wide scan clean)
Comment/XML-doc changes only: - add summaries to ~10k test methods, fixtures, fakes and helpers (+ <param> on theories, <returns> on async Task methods, <inheritdoc/> on interface implementations the checker can resolve) - strip ~2.6k project-tracking references (WP*, P*-*, row-NN, Task N, #NN, Component-0NN) from comments, keeping the explanatory text; reword false positives in comments only - real docs on fakes implementing BCL/library interfaces (IDisposable, ILogger, IOptionsMonitor, IAsyncLifetime) - reword the last 5 src/ false positives (CWE-1236, failures-1, year-0001, M365) Only non-comment edits: four one-line nested classes split across lines so members can carry docs. Build 0 errors / 0 warnings.
This commit is contained in:
+94
-18
@@ -12,7 +12,7 @@ using Xunit;
|
||||
namespace ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests.Repositories;
|
||||
|
||||
/// <summary>
|
||||
/// Bundle D (#23 M1) integration tests for <see cref="AuditLogRepository"/>. Uses
|
||||
/// Integration tests for <see cref="AuditLogRepository"/>. Uses
|
||||
/// the same <see cref="MsSqlMigrationFixture"/> as the Bundle C migration tests so
|
||||
/// raw-SQL paths (the IF NOT EXISTS insert, partition switch) execute against a
|
||||
/// real partitioned schema. Tests scope all queries by a per-test
|
||||
@@ -23,11 +23,15 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
{
|
||||
private readonly MsSqlMigrationFixture _fixture;
|
||||
|
||||
/// <summary>Creates the test class with the shared migrated SQL Server fixture.</summary>
|
||||
/// <param name="fixture">The shared migration fixture.</param>
|
||||
public AuditLogRepositoryTests(MsSqlMigrationFixture fixture)
|
||||
{
|
||||
_fixture = fixture;
|
||||
}
|
||||
|
||||
/// <summary>Verifies that inserting a fresh event writes one row.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task InsertIfNotExistsAsync_FreshEvent_WritesOneRow()
|
||||
{
|
||||
@@ -51,6 +55,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
Assert.Equal(evt.EventId, loaded[0].EventId);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that inserting an event persists its source node.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task InsertIfNotExistsAsync_PersistsSourceNode()
|
||||
{
|
||||
@@ -75,6 +81,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
Assert.Equal("central-a", loaded[0].SourceNode);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that inserting an event with no source node persists a null source node.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task InsertIfNotExistsAsync_PersistsNullSourceNode()
|
||||
{
|
||||
@@ -101,6 +109,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
Assert.Null(loaded[0].SourceNode);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that inserting a duplicate event id is a no-op that neither throws nor duplicates the row.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task InsertIfNotExistsAsync_DuplicateEventId_IsNoOp_NoExceptionNoDuplicate()
|
||||
{
|
||||
@@ -115,7 +125,7 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
await repo.InsertIfNotExistsAsync(first);
|
||||
|
||||
// Same EventId, different payload — first-write-wins, the second call is silently a no-op.
|
||||
// C3 (Task 2.5): ErrorMessage rides in DetailsJson on the canonical record, so rebuild
|
||||
// ErrorMessage rides in DetailsJson on the canonical record, so rebuild
|
||||
// a sibling row carrying the same EventId via the factory (rather than a top-level `with`).
|
||||
var second = ScadaBridgeAuditEventFactory.Create(
|
||||
channel: AuditChannel.ApiOutbound,
|
||||
@@ -133,11 +143,13 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
.ToListAsync();
|
||||
|
||||
Assert.Single(loaded);
|
||||
// C5 (Task 2.5): ErrorMessage rides in DetailsJson now — decode it to assert
|
||||
// ErrorMessage rides in DetailsJson — decode it to assert
|
||||
// first-write-wins kept the original payload.
|
||||
Assert.Equal("first", AuditDetailsCodec.Deserialize(loaded[0].DetailsJson).ErrorMessage);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a query returns rows in descending occurred-time order.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task QueryAsync_ReturnsRowsInOccurredDescOrder()
|
||||
{
|
||||
@@ -161,6 +173,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
Assert.True(rows[1].OccurredAtUtc > rows[2].OccurredAtUtc);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a query can filter by channel.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task QueryAsync_FilterByChannel()
|
||||
{
|
||||
@@ -185,6 +199,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
Assert.All(rows, r => Assert.Equal(AuditChannel.Notification, r.AsRow().Channel));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that filtering by several channels returns their union.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task QueryAsync_FilterByMultipleChannels_ReturnsUnion()
|
||||
{
|
||||
@@ -212,6 +228,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
Assert.DoesNotContain(rows, r => r.AsRow().Channel == AuditChannel.DbOutbound);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that filtering by several statuses returns their union.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task QueryAsync_FilterByMultipleStatuses_ReturnsUnion()
|
||||
{
|
||||
@@ -238,6 +256,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
Assert.DoesNotContain(rows, r => r.AsRow().Status == AuditStatus.Delivered);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that filtering by several source site ids returns their union.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task QueryAsync_FilterByMultipleSourceSiteIds_ReturnsUnion()
|
||||
{
|
||||
@@ -263,6 +283,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
Assert.DoesNotContain(rows, r => r.AsRow().SourceSiteId == siteC);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that an empty channel list does not constrain the query.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task QueryAsync_EmptyChannelList_DoesNotConstrain()
|
||||
{
|
||||
@@ -286,6 +308,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
Assert.Equal(2, rows.Count);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a query can filter by source site id.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task QueryAsync_FilterBySourceSiteId()
|
||||
{
|
||||
@@ -310,12 +334,14 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────────────────────────────
|
||||
// Task 15: SourceNodes filter + GetDistinctSourceNodesAsync. Pins the new
|
||||
// SourceNodes filter + GetDistinctSourceNodesAsync. Pins the new
|
||||
// Node multi-select contract — non-empty list → SQL IN (…); NULL
|
||||
// SourceNode rows are excluded when the filter is set; the distinct
|
||||
// enumeration omits nulls and orders ascending.
|
||||
// ──────────────────────────────────────────────────────────────────────
|
||||
|
||||
/// <summary>Verifies that filtering by source node returns the matching rows.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task QueryAsync_FilterBySourceNode_ReturnsMatchingRows()
|
||||
{
|
||||
@@ -340,6 +366,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
Assert.Equal("central-a", rows[0].SourceNode);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that filtering by several source nodes returns their union.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task QueryAsync_FilterByMultipleSourceNodes_ReturnsUnion()
|
||||
{
|
||||
@@ -364,6 +392,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
Assert.All(rows, r => Assert.Contains(r.SourceNode, new[] { "central-a", "central-b" }));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the distinct source nodes are returned without nulls and in ascending order.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task GetDistinctSourceNodesAsync_ReturnsDistinctNonNullValues_Ordered()
|
||||
{
|
||||
@@ -394,6 +424,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
Assert.Equal(nodes.OrderBy(n => n, StringComparer.Ordinal), nodes);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that filtering by execution id returns the matching rows.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task QueryAsync_FilterByExecutionId_ReturnsMatchingRows()
|
||||
{
|
||||
@@ -422,6 +454,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
Assert.All(rows, r => Assert.Equal(executionId, r.AsRow().ExecutionId));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that filtering by parent execution id returns the matching rows.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task QueryAsync_FilterByParentExecutionId_ReturnsMatchingRows()
|
||||
{
|
||||
@@ -451,6 +485,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
Assert.All(rows, r => Assert.Equal(parentExecutionId, r.AsRow().ParentExecutionId));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a query can filter by time range.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task QueryAsync_FilterByTimeRange()
|
||||
{
|
||||
@@ -476,6 +512,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
Assert.Equal(t0.AddMinutes(30), rows[0].OccurredAtUtc);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the next keyset page starts after the cursor.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task QueryAsync_Keyset_NextPageStartsAfterCursor()
|
||||
{
|
||||
@@ -525,6 +563,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
Assert.Equal(t0.AddMinutes(0), page3[0].OccurredAtUtc);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that concurrent duplicate inserts produce exactly one row.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task InsertIfNotExistsAsync_ConcurrentDuplicateInserts_ProduceExactlyOneRow()
|
||||
{
|
||||
@@ -561,9 +601,11 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// WP2.2: set-based InsertManyIfNotExistsAsync
|
||||
// Set-based InsertManyIfNotExistsAsync
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/// <summary>Verifies that a batch insert writes every distinct event.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task InsertManyIfNotExistsAsync_WritesEveryDistinctEvent()
|
||||
{
|
||||
@@ -593,6 +635,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
rows.Select(r => r.EventId).OrderBy(g => g).ToArray());
|
||||
}
|
||||
|
||||
/// <summary>Verifies that duplicate event ids within one batch collapse to a single row.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task InsertManyIfNotExistsAsync_DuplicateEventIdsWithinOnePacket_CollapseToOneRow()
|
||||
{
|
||||
@@ -638,6 +682,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
Assert.Null(AuditDetailsCodec.Deserialize(stored.DetailsJson).ErrorMessage);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that duplicate event ids across batches are inserted idempotently.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task InsertManyIfNotExistsAsync_DuplicateEventIdsAcrossPackets_AreIdempotent()
|
||||
{
|
||||
@@ -675,6 +721,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
Assert.Equal(6, rows.Count);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a batch larger than the SQL parameter ceiling is inserted in chunks.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task InsertManyIfNotExistsAsync_ChunksBeyondTheParameterCeiling()
|
||||
{
|
||||
@@ -718,6 +766,7 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
/// server raise 2628/8152. Reject-everywhere is the contract; this test pins
|
||||
/// both halves of it.
|
||||
/// </summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task InsertManyIfNotExistsAsync_TargetLongerThanColumn_IsRejected_NotTruncated()
|
||||
{
|
||||
@@ -736,7 +785,7 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
var batchRepo = new AuditLogRepository(batchContext);
|
||||
|
||||
// 2628 = "String or binary data would be truncated in table …" (SQL 2019+),
|
||||
// 8152 = its pre-2019 predecessor. Either proves the server saw the full value.
|
||||
// 8152 = its predecessor on SQL Server versions before 2019. Either proves the server saw the full value.
|
||||
var batchEx = await Assert.ThrowsAsync<SqlException>(
|
||||
() => batchRepo.InsertManyIfNotExistsAsync(new[] { evt }));
|
||||
Assert.Contains(batchEx.Number, new[] { 2628, 8152 });
|
||||
@@ -761,6 +810,7 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
/// The companion to the rejection test: a value that FITS must still round-trip
|
||||
/// through the set-based path byte for byte, at the exact column boundary.
|
||||
/// </summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task InsertManyIfNotExistsAsync_TargetAtColumnLimit_RoundTripsIntact()
|
||||
{
|
||||
@@ -786,6 +836,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
Assert.Equal(boundaryTarget, loaded[0].Target);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that inserting an empty batch is a no-op.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task InsertManyIfNotExistsAsync_EmptyBatch_IsANoOp()
|
||||
{
|
||||
@@ -797,6 +849,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
Assert.Equal(0, await repo.InsertManyIfNotExistsAsync(Array.Empty<AuditEvent>()));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that keyset paging breaks ties on event id when rows share an occurred time.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task QueryAsync_Keyset_SameOccurredAtUtc_TiebreaksOnEventId()
|
||||
{
|
||||
@@ -855,12 +909,12 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// M6-T4 Bundle C: SwitchOutPartitionAsync drop-and-rebuild integration tests
|
||||
// SwitchOutPartitionAsync drop-and-rebuild integration tests
|
||||
// ------------------------------------------------------------------------
|
||||
//
|
||||
// The partition-switch path replaces M1's NotSupportedException stub with
|
||||
// The partition-switch path replaces the earlier NotSupportedException stub with
|
||||
// the production CREATE-staging → SWITCH PARTITION → DROP-staging batch
|
||||
// documented in alog.md §4. WP2.2 removed the index drop/rebuild that used to
|
||||
// documented in alog.md §4. The design removed the index drop/rebuild that used to
|
||||
// bracket it: uniqueness rides the partition-ALIGNED clustered PK
|
||||
// (EventId, OccurredAtUtc), so SWITCH has nothing to object to. These tests
|
||||
// verify the side effects an outsider can observe:
|
||||
@@ -871,6 +925,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
// after a switch (the aligned key really does enforce it)
|
||||
// * a thrown SqlException leaves the table intact with no orphaned staging
|
||||
|
||||
/// <summary>Verifies that switching out an old partition removes its rows and keeps newer partitions.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task SwitchOutPartitionAsync_OldPartition_RemovesRows_NewPartitionsKept()
|
||||
{
|
||||
@@ -906,6 +962,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
Assert.Contains(remaining, e => e.EventId == marEvt.EventId);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a partition switch leaves no non-aligned unique index behind.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task SwitchOutPartitionAsync_LeavesNoNonAlignedUniqueIndex_AfterSwitch()
|
||||
{
|
||||
@@ -918,7 +976,7 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
// the fixture's MSSQL database) don't tread on each other.
|
||||
await repo.SwitchOutPartitionAsync(new DateTime(2026, 4, 1, 0, 0, 0, DateTimeKind.Utc));
|
||||
|
||||
// WP2.2: the switch must NOT recreate UX_AuditLog_EventId. Re-adding it
|
||||
// The switch must NOT recreate UX_AuditLog_EventId. Re-adding it
|
||||
// would reinstate the offline drop/rebuild the purge was freed from and
|
||||
// block the next SWITCH until something dropped it again.
|
||||
await using var verifyContext = CreateContext();
|
||||
@@ -937,6 +995,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
Assert.Equal(1, pkExists);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that first-write-wins insertion is still enforced after a partition switch.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task SwitchOutPartitionAsync_InsertIfNotExistsAsync_StillEnforcesFirstWriteWins_AfterSwitch()
|
||||
{
|
||||
@@ -959,7 +1019,7 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
// column instead of a dedicated unique index; if the switch had disturbed
|
||||
// that key, this insert would silently produce a duplicate row and the
|
||||
// count assertion below would catch it.
|
||||
// C3 (Task 2.5): rebuild a sibling row with the same EventId via the factory
|
||||
// Rebuild a sibling row with the same EventId via the factory
|
||||
// (ErrorMessage rides in DetailsJson, so a top-level `with` no longer applies).
|
||||
var dup = ScadaBridgeAuditEventFactory.Create(
|
||||
channel: AuditChannel.ApiOutbound,
|
||||
@@ -978,11 +1038,13 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
|
||||
Assert.Single(rows);
|
||||
Assert.Equal(preExisting.EventId, rows[0].EventId);
|
||||
// First-write-wins: the original ErrorMessage (null) survives. C5 (Task 2.5):
|
||||
// First-write-wins: the original ErrorMessage (null) survives.
|
||||
// ErrorMessage rides in DetailsJson — decode it to assert.
|
||||
Assert.Null(AuditDetailsCodec.Deserialize(rows[0].DetailsJson).ErrorMessage);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a partial partition-switch failure raises an exception and leaves no orphaned staging table.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task SwitchOutPartitionAsync_PartialFailure_RaisesException_LeavesNoOrphanedStaging()
|
||||
{
|
||||
@@ -1045,8 +1107,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
"SELECT COUNT(*) FROM sys.tables WHERE name LIKE 'AuditLog\\_Staging\\_%' ESCAPE '\\';");
|
||||
Assert.Equal(0, orphanedStaging);
|
||||
|
||||
// And it must NOT have (re)created the non-aligned unique index: WP2.2
|
||||
// deleted that rebuild entirely, so a failed switch cannot reintroduce
|
||||
// And it must NOT have (re)created the non-aligned unique index: the
|
||||
// design deleted that rebuild entirely, so a failed switch cannot reintroduce
|
||||
// the object that blocks the NEXT switch.
|
||||
var indexExists = await ScalarAsync<int>(
|
||||
verifyContext,
|
||||
@@ -1056,9 +1118,11 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// M6-T4 Bundle C: GetPartitionBoundariesOlderThanAsync
|
||||
// GetPartitionBoundariesOlderThanAsync
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/// <summary>Verifies that only partition boundaries whose newest row is older than the threshold are returned.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task GetPartitionBoundariesOlderThanAsync_ReturnsBoundaries_WithMaxOccurredOlderThanThreshold()
|
||||
{
|
||||
@@ -1087,7 +1151,7 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// M7-T13 Bundle E: GetKpiSnapshotAsync — Health-dashboard Audit KPI tiles
|
||||
// GetKpiSnapshotAsync — Health-dashboard Audit KPI tiles
|
||||
// ------------------------------------------------------------------------
|
||||
//
|
||||
// The dashboard's "Audit volume" tile reads TotalEventsLastHour and the
|
||||
@@ -1102,6 +1166,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
// narrow band centred on that anchor — no other test in this class seeds
|
||||
// there, so the global count equals the seeded count for that band.
|
||||
|
||||
/// <summary>Verifies that the KPI snapshot reports correct totals and error counts for rows of mixed status.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task GetKpiSnapshotAsync_WithMixedStatusRows_ReturnsCorrectTotalsAndErrors()
|
||||
{
|
||||
@@ -1141,6 +1207,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
Assert.Equal(nowUtc, snapshot.AsOfUtc);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the KPI snapshot of an empty window reports zero totals.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task GetKpiSnapshotAsync_EmptyWindow_ReturnsZeroTotals()
|
||||
{
|
||||
@@ -1163,7 +1231,7 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Audit Log ParentExecutionId (Task 8): GetExecutionTreeAsync
|
||||
// Audit Log ParentExecutionId: GetExecutionTreeAsync
|
||||
// ------------------------------------------------------------------------
|
||||
//
|
||||
// GetExecutionTreeAsync walks UP from any node to the chain root, then walks
|
||||
@@ -1175,6 +1243,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
// * pathological cyclic data is bounded by the MAXRECURSION guard and
|
||||
// surfaces a SqlException rather than hanging
|
||||
|
||||
/// <summary>Verifies that the execution tree resolves a multi-level parent chain.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task GetExecutionTree_MultiLevelChain()
|
||||
{
|
||||
@@ -1267,6 +1337,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the execution tree edge scan is bounded to the root window.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task ExecutionTree_Bounds_EdgeScan_To_Root_Window()
|
||||
{
|
||||
@@ -1310,6 +1382,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
Assert.Equal(2, tree.Count);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the execution tree includes a stub node for a parent with no audit rows.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task GetExecutionTree_StubParentNode()
|
||||
{
|
||||
@@ -1351,6 +1425,8 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
Assert.Equal(stubParentExec, child.ParentExecutionId);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the execution tree walk respects the maximum recursion depth.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[SkippableFact]
|
||||
public async Task GetExecutionTree_RespectsMaxRecursion()
|
||||
{
|
||||
@@ -1413,7 +1489,7 @@ public class AuditLogRepositoryTests : IClassFixture<MsSqlMigrationFixture>
|
||||
private static string NewSiteId() =>
|
||||
"test-bundle-d-" + Guid.NewGuid().ToString("N").Substring(0, 8);
|
||||
|
||||
// C3 (Task 2.5): build the canonical ZB.MOM.WW.Audit.AuditEvent via the shared
|
||||
// Build the canonical ZB.MOM.WW.Audit.AuditEvent via the shared
|
||||
// factory; the repository's transitional shim decomposes it into the 24-column
|
||||
// AuditLogRow on INSERT and recomposes the canonical record on QUERY.
|
||||
private static AuditEvent NewEvent(
|
||||
|
||||
Reference in New Issue
Block a user