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:
+60
-7
@@ -10,7 +10,7 @@ using ZB.MOM.WW.ScadaBridge.SiteRuntime.Tracking;
|
||||
namespace ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests.Tracking;
|
||||
|
||||
/// <summary>
|
||||
/// Audit Log #23 (M3 Bundle A — Task A2) — schema + behaviour tests for the
|
||||
/// Schema + behaviour tests for the
|
||||
/// site-local <see cref="OperationTrackingStore"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
@@ -36,6 +36,7 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
private readonly List<ServiceProvider> _providers = [];
|
||||
private readonly List<string> _tempFiles = [];
|
||||
|
||||
/// <summary>Releases the resources held by this test class.</summary>
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (var provider in _providers)
|
||||
@@ -102,6 +103,7 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
return connection;
|
||||
}
|
||||
|
||||
/// <summary>Verifies that constructing the store creates the operation tracking schema on first use.</summary>
|
||||
[Fact]
|
||||
public void Constructor_CreatesOperationTracking_SchemaOnFirstUse()
|
||||
{
|
||||
@@ -136,6 +138,7 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that initialization creates the operation tracking table with a SourceNode column.</summary>
|
||||
[Fact]
|
||||
public void Initialize_creates_OperationTracking_with_SourceNode_column()
|
||||
{
|
||||
@@ -202,6 +205,8 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
private OperationTrackingStore CreateStoreOver(string databasePath)
|
||||
=> new(CreateLocalDb(databasePath), NullLogger<OperationTrackingStore>.Instance);
|
||||
|
||||
/// <summary>Verifies that initialization adds the SourceNode column to a pre-existing schema.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task Initialize_adds_SourceNode_to_pre_existing_schema()
|
||||
{
|
||||
@@ -255,6 +260,8 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that recording an enqueue persists the source node.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task RecordEnqueueAsync_persists_SourceNode()
|
||||
{
|
||||
@@ -275,6 +282,8 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
Assert.Equal("node-a", snapshot!.SourceNode);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that recording an enqueue persists a null source node.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task RecordEnqueueAsync_persists_null_SourceNode()
|
||||
{
|
||||
@@ -295,6 +304,8 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
Assert.Null(snapshot!.SourceNode);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that recording an enqueue inserts a submitted row with a retry count of zero.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task RecordEnqueueAsync_InsertsSubmittedRow_WithRetryCountZero()
|
||||
{
|
||||
@@ -326,6 +337,8 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
Assert.Equal(DateTimeKind.Utc, snapshot.UpdatedAtUtc.Kind);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a duplicate enqueue is a no-op and the first write wins.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task RecordEnqueueAsync_Duplicate_IsNoOp_FirstWriteWins()
|
||||
{
|
||||
@@ -346,6 +359,8 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
Assert.Equal(0, snapshot.RetryCount);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that recording an attempt advances the status and retry count on a non-terminal row.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task RecordAttemptAsync_AdvancesStatusAndRetryCount_OnNonTerminalRow()
|
||||
{
|
||||
@@ -374,6 +389,8 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
Assert.True(snapshot.UpdatedAtUtc >= snapshot.CreatedAtUtc);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that recording an attempt on a terminal row is a no-op.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task RecordAttemptAsync_OnTerminalRow_IsNoOp()
|
||||
{
|
||||
@@ -409,6 +426,8 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
Assert.NotNull(afterLate.TerminalAtUtc);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that recording a terminal outcome flips the row to terminal and sets the terminal timestamp.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task RecordTerminalAsync_FlipsToTerminal_WithTerminalAtUtcSet()
|
||||
{
|
||||
@@ -435,6 +454,8 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
Assert.Equal(503, snapshot.HttpStatus);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that getting the status of an unknown operation returns null.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task GetStatusAsync_Unknown_ReturnsNull()
|
||||
{
|
||||
@@ -447,6 +468,8 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
Assert.Null(snapshot);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that getting the status returns the latest snapshot after multiple attempts.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task GetStatusAsync_ReturnsLatestSnapshot_AfterMultipleAttempts()
|
||||
{
|
||||
@@ -466,6 +489,8 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
Assert.Equal(504, snapshot.HttpStatus);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that purging removes old terminal rows while keeping recent and non-terminal rows.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task PurgeTerminalAsync_RemovesOldTerminalRows_KeepsRecent_KeepsNonTerminal()
|
||||
{
|
||||
@@ -510,8 +535,10 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
Assert.NotNull(await store.GetStatusAsync(cId)); // kept (non-terminal)
|
||||
}
|
||||
|
||||
// ── Site Call Audit #22: ReadChangedSinceAsync (reconciliation pull) ───
|
||||
// ── Site call audit: ReadChangedSinceAsync (reconciliation pull) ───
|
||||
|
||||
/// <summary>Verifies that the changed-since read returns rows at or after the cursor, oldest first.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task ReadChangedSinceAsync_ReturnsRowsAtOrAfterCursor_OldestFirst()
|
||||
{
|
||||
@@ -546,6 +573,8 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
Assert.True(result[0].UpdatedAtUtc <= result[1].UpdatedAtUtc);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the changed-since read from the minimum timestamp returns all rows.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task ReadChangedSinceAsync_FromMinValue_ReturnsAllRows()
|
||||
{
|
||||
@@ -560,6 +589,8 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
Assert.Equal(2, result.Count);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the changed-since read is capped to the batch size.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task ReadChangedSinceAsync_IsBatchCapped()
|
||||
{
|
||||
@@ -587,6 +618,8 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
Assert.Equal(ids[2], result[2].TrackedOperationId);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the changed-since read maps a tracking row onto the site call operational record.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task ReadChangedSinceAsync_MapsTrackingRowOntoSiteCallOperational()
|
||||
{
|
||||
@@ -647,6 +680,8 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
// ── 2026-09-06: writes off the script thread (single-writer queue) ─────
|
||||
// Design: docs/plans/2026-09-06-tracking-store-async-writes-design.md
|
||||
|
||||
/// <summary>Verifies that a write returns while another connection holds the write lock and lands once it is released.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task Write_ReturnsWhileAnotherConnectionHoldsTheWriteLock_AndLandsOnceReleased()
|
||||
{
|
||||
@@ -684,6 +719,8 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that reads see every write queued before them, in order.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task Reads_SeeEveryWriteQueuedBeforeThem_InOrder()
|
||||
{
|
||||
@@ -714,6 +751,8 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that async dispose drains queued writes before closing the connection.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task DisposeAsync_DrainsQueuedWrites_BeforeClosingTheConnection()
|
||||
{
|
||||
@@ -731,6 +770,8 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
Assert.Equal(200L, (long)count.ExecuteScalar()!);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that writing after dispose throws an object-disposed exception.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task Write_AfterDispose_ThrowsObjectDisposed()
|
||||
{
|
||||
@@ -740,12 +781,14 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
store.RecordEnqueueAsync(TrackedOperationId.New(), "ApiCallCached", null, null, null, null));
|
||||
}
|
||||
|
||||
// ── SiteRuntime-024: read/write split + sync-safe Dispose ──────────────
|
||||
// ── Read/write split + sync-safe Dispose ──────────────
|
||||
|
||||
/// <summary>Verifies that concurrent reads do not block on an in-flight write.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task SR024_ConcurrentReads_DoNotBlockOnInFlightWrite()
|
||||
{
|
||||
// Regression test for SiteRuntime-024 (perf half). Pre-fix, every
|
||||
// Regression test for the read/write split (perf half). Pre-fix, every
|
||||
// GetStatusAsync took the same _gate as RecordTerminalAsync, so a single
|
||||
// long-running write would queue up every concurrent status query. After
|
||||
// the fix, reads open a fresh SqliteConnection per call and don't take
|
||||
@@ -786,10 +829,12 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a synchronous dispose from a fresh thread does not deadlock.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task SR024_SyncDispose_DoesNotDeadlock_WhenInvokedFromFreshThread()
|
||||
{
|
||||
// Regression test for SiteRuntime-024 (deadlock half). Pre-fix, Dispose
|
||||
// Regression test for the sync-safe Dispose (deadlock half). Pre-fix, Dispose
|
||||
// bridged to async via DisposeAsyncCore().AsTask().GetAwaiter().GetResult()
|
||||
// — sync-over-async on a SemaphoreSlim can deadlock under a non-reentrant
|
||||
// SyncContext (host shutdown continuations). Post-fix, Dispose runs
|
||||
@@ -828,6 +873,8 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
Assert.True(await disposeReturned.Task);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that async dispose does not deadlock and is idempotent.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task SR024_AsyncDispose_DoesNotDeadlock_AndIsIdempotent()
|
||||
{
|
||||
@@ -851,8 +898,10 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
await store.DisposeAsync();
|
||||
}
|
||||
|
||||
// ── Task 24: pin the inclusive (>=) reconciliation cursor boundary ──
|
||||
// ── Pin the inclusive (>=) reconciliation cursor boundary ──
|
||||
|
||||
/// <summary>Verifies that the changed-since boundary timestamp is inclusive and an upsert on a newer status absorbs duplicates.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task ReadChangedSince_BoundaryTimestamp_IsInclusive_UpsertOnNewerAbsorbsDuplicates()
|
||||
{
|
||||
@@ -895,7 +944,7 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
Assert.Equal(2, rows.Count);
|
||||
}
|
||||
|
||||
// ── Task 15: composite (UpdatedAtUtc, TrackedOperationId) keyset ──
|
||||
// ── Composite (UpdatedAtUtc, TrackedOperationId) keyset ──
|
||||
|
||||
/// <summary>
|
||||
/// Seeds <c>batchSize + 2</c> rows that all share ONE <c>UpdatedAtUtc</c> and
|
||||
@@ -904,6 +953,7 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
/// returns the REMAINING rows with no overlap — the stall the plain inclusive
|
||||
/// <c>>=</c> resume can never escape.
|
||||
/// </summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task ReadChangedSince_CompositeKeyset_AdvancesPastSharedTimestamp()
|
||||
{
|
||||
@@ -945,6 +995,7 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
/// shared timestamp re-reads the same page (the exact stall the keyset fixes) —
|
||||
/// an older central that never sends <c>after_id</c> is byte-for-byte unaffected.
|
||||
/// </summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task ReadChangedSince_WithoutKeyset_ReReadsSamePage_LegacyPreserved()
|
||||
{
|
||||
@@ -984,6 +1035,8 @@ public class OperationTrackingStoreTests : IDisposable
|
||||
cmd.ExecuteNonQuery();
|
||||
return boundary;
|
||||
}
|
||||
/// <summary>Verifies that a synchronous dispose does not close the connection while the writer gate is held.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task ORCH1_SyncDisposeDoesNotCloseConnectionWhileWriterGateIsHeld()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user