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:
Joseph Doherty
2026-10-07 15:05:49 -04:00
parent 0ffd4bdbea
commit 513fa1aa16
998 changed files with 17896 additions and 2395 deletions
@@ -14,8 +14,8 @@ using ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests.Migrations;
namespace ZB.MOM.WW.ScadaBridge.SiteCallAudit.Tests;
/// <summary>
/// Bundle C1 (#22, #23 M3) tests for <see cref="SiteCallAuditActor"/>. Uses the
/// same <see cref="MsSqlMigrationFixture"/> as the Bundle B3 repository tests
/// Tests for <see cref="SiteCallAuditActor"/>. Uses the
/// same <see cref="MsSqlMigrationFixture"/> as the repository tests
/// so the actor exercises the real monotonic-upsert SQL end to end against the
/// <c>SiteCalls</c> schema. Each test scopes its data by minting a fresh
/// <see cref="TrackedOperationId"/> (and a per-test <c>SourceSite</c> suffix)
@@ -25,6 +25,8 @@ public class SiteCallAuditActorTests : TestKit, IClassFixture<MsSqlMigrationFixt
{
private readonly MsSqlMigrationFixture _fixture;
/// <summary>Initializes the test class with the shared MSSQL migration fixture.</summary>
/// <param name="fixture">The shared MSSQL migration fixture.</param>
public SiteCallAuditActorTests(MsSqlMigrationFixture fixture)
{
_fixture = fixture;
@@ -87,6 +89,8 @@ public class SiteCallAuditActorTests : TestKit, IClassFixture<MsSqlMigrationFixt
NullLogger<SiteCallAuditActor>.Instance)));
}
/// <summary>Verifies that an upsert command is persisted and acknowledged as accepted.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[SkippableFact]
public async Task Receive_UpsertSiteCallCommand_Persists_Replies_Accepted()
{
@@ -116,6 +120,8 @@ public class SiteCallAuditActorTests : TestKit, IClassFixture<MsSqlMigrationFixt
Assert.Equal("Submitted", rows[0].Status);
}
/// <summary>Verifies that a duplicate upsert with an older status changes nothing yet is still acknowledged as accepted.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[SkippableFact]
public async Task Receive_DuplicateUpsert_OlderStatus_NoOp_StillRepliesAccepted()
{
@@ -143,7 +149,7 @@ public class SiteCallAuditActorTests : TestKit, IClassFixture<MsSqlMigrationFixt
var secondReply = ExpectMsg<UpsertSiteCallReply>(TimeSpan.FromSeconds(10));
Assert.True(secondReply.Accepted, "Stale upsert must still be acked (idempotent contract).");
// Storage must still show the rank-2 row, not rolled back.
// Storage must still show the rank 2 row, not rolled back.
await using var readContext = CreateContext();
var stored = await readContext.Set<SiteCall>()
.Where(s => s.TrackedOperationId == id)
@@ -154,6 +160,8 @@ public class SiteCallAuditActorTests : TestKit, IClassFixture<MsSqlMigrationFixt
Assert.Equal("first", stored[0].LastError);
}
/// <summary>Verifies that a transient repository failure replies not-accepted and leaves the actor alive.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[SkippableFact]
public async Task Receive_RepoThrowsTransient_RepliesAccepted_False_ActorStaysAlive()
{
@@ -194,8 +202,10 @@ public class SiteCallAuditActorTests : TestKit, IClassFixture<MsSqlMigrationFixt
Assert.Equal(healthyId, rows[0].TrackedOperationId);
}
// ── Task 4: read-side (query / detail / KPI) handlers ──
// ── Read-side (query / detail / KPI) handlers ──
/// <summary>Verifies that filtering a query by source site returns only the matching summaries.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[SkippableFact]
public async Task SiteCallQueryRequest_FilterBySourceSite_ReturnsMatchingSummaries()
{
@@ -231,10 +241,12 @@ public class SiteCallAuditActorTests : TestKit, IClassFixture<MsSqlMigrationFixt
Assert.Equal(response.SiteCalls[^1].TrackedOperationId, response.NextAfterId);
}
/// <summary>Verifies that filtering a query by source node returns only the matching summaries.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[SkippableFact]
public async Task SiteCallQueryRequest_FilterBySourceNode_ReturnsMatchingSummaries()
{
// Task 17: the new Node filter input pushes a string into
// The new Node filter input pushes a string into
// SiteCallQueryRequest.SourceNodeFilter — the actor must thread it
// onto SiteCallQueryFilter.SourceNode and the response summaries must
// mirror the row's SourceNode column.
@@ -268,10 +280,12 @@ public class SiteCallAuditActorTests : TestKit, IClassFixture<MsSqlMigrationFixt
Assert.Equal("Attempted", response.SiteCalls[0].Status);
}
/// <summary>Verifies that filtering a query by tracked operation id returns only that row.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[SkippableFact]
public async Task SiteCallQueryRequest_FilterByTrackedOperationId_ReturnsOnlyThatRow()
{
// Flow Debugger follow-ups Task 2: the ?correlationId= deep link pushes
// Flow Debugger follow-up: the ?correlationId= deep link pushes
// one operation id into SiteCallQueryRequest.TrackedOperationIdFilter —
// the actor must thread it onto SiteCallQueryFilter.TrackedOperationId
// so the page returns exactly that row and nothing else from the site.
@@ -307,6 +321,8 @@ public class SiteCallAuditActorTests : TestKit, IClassFixture<MsSqlMigrationFixt
Assert.Equal(rowA.TrackedOperationId.Value, response.NextAfterId);
}
/// <summary>Verifies that keyset paging advances through the results via the cursor.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[SkippableFact]
public async Task SiteCallQueryRequest_KeysetPaging_AdvancesViaCursor()
{
@@ -344,6 +360,8 @@ public class SiteCallAuditActorTests : TestKit, IClassFixture<MsSqlMigrationFixt
Assert.Equal(3, allIds.Count);
}
/// <summary>Verifies that the stuck-only filter returns only old, non-terminal rows.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[SkippableFact]
public async Task SiteCallQueryRequest_StuckOnly_ReturnsOnlyOldNonTerminalRows()
{
@@ -379,6 +397,8 @@ public class SiteCallAuditActorTests : TestKit, IClassFixture<MsSqlMigrationFixt
Assert.True(response.SiteCalls[0].IsStuck);
}
/// <summary>Verifies that stuck-only pages are full and never come back under-filled with a next cursor.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[SkippableFact]
public async Task SiteCallQueryRequest_StuckOnly_PagesAreFull_NoEmptyPagesWithCursor()
{
@@ -392,7 +412,7 @@ public class SiteCallAuditActorTests : TestKit, IClassFixture<MsSqlMigrationFixt
var now = DateTime.UtcNow;
// Three stuck rows interleaved (by CreatedAtUtc) with three non-stuck
// rows: recent non-terminal and old-but-terminal. With the StuckOnly
// filter pushed into SQL, a page-size-2 query must return exactly the
// filter pushed into SQL, a page-size-of-two query must return exactly the
// stuck rows two-per-page — never an under-filled page with a non-null
// next cursor caused by post-filtering.
for (var i = 0; i < 3; i++)
@@ -438,13 +458,15 @@ public class SiteCallAuditActorTests : TestKit, IClassFixture<MsSqlMigrationFixt
Assert.Equal(3, allIds.Count);
}
/// <summary>Verifies that a stuck-only cursor sitting on a non-stuck row skips to the next stuck row.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[SkippableFact]
public async Task SiteCallQueryRequest_StuckOnly_CursorAtNonStuckBoundary_SkipsToNextStuckRow()
{
// SiteCallAudit-006 boundary regression. The earlier paging test
// interleaves stuck/non-stuck rows but the cursor between page-1 and
// page-2 always lands on a stuck row. This test forces the cursor to
// sit on a NON-stuck row (page-size=1 over a strict
// Boundary regression. The earlier paging test
// interleaves stuck/non-stuck rows but the cursor between page 1 and
// page 2 always lands on a stuck row. This test forces the cursor to
// sit on a NON-stuck row (a page size of 1 over a strict
// stuck-not_stuck-stuck-not_stuck-stuck-not_stuck pattern oldest-first)
// so the SQL-side composition of the stuck predicate AND the keyset
// cursor predicate (CreatedAtUtc < cursor OR =cursor AND id < ...) must
@@ -470,7 +492,7 @@ public class SiteCallAuditActorTests : TestKit, IClassFixture<MsSqlMigrationFixt
// t=-35m (stuck — Attempted, 35m > 10m: stuckC),
// t=-40m (non-stuck — terminal Delivered, oldest of all).
// The non-stuck rows at -20m and -30m sit between consecutive stuck
// rows, so the page-size-1 cursor lands ON a non-stuck row between
// rows, so a page-size-of-one cursor lands ON a non-stuck row between
// pages — exactly the boundary the predicate composition must skip.
var stuckA = TrackedOperationId.New();
var stuckB = TrackedOperationId.New();
@@ -502,7 +524,7 @@ public class SiteCallAuditActorTests : TestKit, IClassFixture<MsSqlMigrationFixt
TrackedOperationId.New(), siteId, status: "Attempted",
createdAtUtc: now.AddMinutes(-1)));
// Page-1: page-size=1, expect stuckA (newest stuck row).
// Page 1: page size of 1, expect stuckA (newest stuck row).
actor.Tell(
new SiteCallQueryRequest(
"corr-stuck-b1", null, siteId, null, null, StuckOnly: true,
@@ -515,7 +537,7 @@ public class SiteCallAuditActorTests : TestKit, IClassFixture<MsSqlMigrationFixt
Assert.Equal(stuckA.Value, page1.SiteCalls[0].TrackedOperationId);
Assert.NotNull(page1.NextAfterCreatedAtUtc);
// Page-2: between stuckA and stuckB the non-stuck terminal row at -20m
// Page 2: between stuckA and stuckB the non-stuck terminal row at -20m
// sits at the cursor — the SQL must skip it, NOT return it.
actor.Tell(
new SiteCallQueryRequest(
@@ -530,7 +552,7 @@ public class SiteCallAuditActorTests : TestKit, IClassFixture<MsSqlMigrationFixt
Assert.Equal(stuckB.Value, page2.SiteCalls[0].TrackedOperationId);
Assert.NotNull(page2.NextAfterCreatedAtUtc);
// Page-3: between stuckB and stuckC the non-stuck row at -30m sits at
// Page 3: between stuckB and stuckC the non-stuck row at -30m sits at
// the cursor — again must be skipped.
actor.Tell(
new SiteCallQueryRequest(
@@ -553,6 +575,8 @@ public class SiteCallAuditActorTests : TestKit, IClassFixture<MsSqlMigrationFixt
Assert.Equal(stuckIds, visited);
}
/// <summary>Verifies that a detail request for a known id returns the full detail.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[SkippableFact]
public async Task SiteCallDetailRequest_KnownId_ReturnsFullDetail()
{
@@ -582,6 +606,8 @@ public class SiteCallAuditActorTests : TestKit, IClassFixture<MsSqlMigrationFixt
Assert.Equal("node-a", response.Detail.SourceNode);
}
/// <summary>Verifies that a detail request for an unknown id replies not found.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[SkippableFact]
public async Task SiteCallDetailRequest_UnknownId_RepliesNotFound()
{
@@ -599,6 +625,8 @@ public class SiteCallAuditActorTests : TestKit, IClassFixture<MsSqlMigrationFixt
Assert.NotNull(response.ErrorMessage);
}
/// <summary>Verifies that a KPI request computes point-in-time counts.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[SkippableFact]
public async Task SiteCallKpiRequest_ComputesPointInTimeCounts()
{
@@ -641,8 +669,10 @@ public class SiteCallAuditActorTests : TestKit, IClassFixture<MsSqlMigrationFixt
Assert.NotNull(response.OldestPendingAge);
}
// ── Per-node KPI (T6: M5.2 per-node stuck-count KPIs) ──────────────────
// ── Per-node KPI (per-node stuck-count KPIs) ──────────────────
/// <summary>Verifies that the per-node KPI request scopes the counts to each node.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[SkippableFact]
public async Task PerNodeSiteCallKpiRequest_ScopesCountsToEachNode()
{
@@ -678,6 +708,8 @@ public class SiteCallAuditActorTests : TestKit, IClassFixture<MsSqlMigrationFixt
Assert.NotNull(myNode.OldestPendingAge);
}
/// <summary>Verifies that the per-site KPI request scopes the counts to each site.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[SkippableFact]
public async Task PerSiteSiteCallKpiRequest_ScopesCountsToEachSite()
{
@@ -712,6 +744,8 @@ public class SiteCallAuditActorTests : TestKit, IClassFixture<MsSqlMigrationFixt
Assert.NotNull(mySite.OldestPendingAge);
}
/// <summary>Verifies that a repository failure during a query replies with a failure and leaves the actor alive.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[SkippableFact]
public async Task SiteCallQueryRequest_RepoThrows_RepliesFailure_ActorStaysAlive()
{
@@ -734,14 +768,16 @@ public class SiteCallAuditActorTests : TestKit, IClassFixture<MsSqlMigrationFixt
Assert.Equal("corr-fault", response.CorrelationId);
}
// ── SourceNode-stamping (Task 14): end-to-end actor → repo persistence ──
// ── SourceNode-stamping: end-to-end actor → repo persistence ──
/// <summary>Verifies that an upsert command persists its source node end to end.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[SkippableFact]
public async Task UpsertSiteCallCommand_PersistsSourceNode_EndToEnd()
{
Skip.IfNot(_fixture.Available, _fixture.SkipReason);
// SourceNode-stamping (Task 14): an UpsertSiteCallCommand carrying
// SourceNode-stamping: an UpsertSiteCallCommand carrying
// SourceNode "node-a" must land in the SiteCalls row's SourceNode
// column unchanged — verifies the actor's mapping path does not
// strip the column AND the repository INSERT writes it.
@@ -765,6 +801,8 @@ public class SiteCallAuditActorTests : TestKit, IClassFixture<MsSqlMigrationFixt
Assert.Equal("node-a", stored[0].SourceNode);
}
/// <summary>Verifies that an upsert command with a null source node persists null.</summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[SkippableFact]
public async Task UpsertSiteCallCommand_NullSourceNode_PersistsNull()
{
@@ -804,32 +842,41 @@ public class SiteCallAuditActorTests : TestKit, IClassFixture<MsSqlMigrationFixt
{
private readonly ISiteCallAuditRepository _inner;
/// <summary>Initializes the repository wrapper.</summary>
/// <param name="inner">The real repository that every call except <c>QueryAsync</c> delegates to.</param>
public QueryThrowingRepository(ISiteCallAuditRepository inner)
{
_inner = inner;
}
/// <inheritdoc />
public Task UpsertAsync(SiteCall siteCall, CancellationToken ct = default) =>
_inner.UpsertAsync(siteCall, ct);
/// <inheritdoc />
public Task<SiteCall?> GetAsync(TrackedOperationId id, CancellationToken ct = default) =>
_inner.GetAsync(id, ct);
/// <inheritdoc />
public Task<IReadOnlyList<SiteCall>> QueryAsync(
SiteCallQueryFilter filter, SiteCallPaging paging, CancellationToken ct = default) =>
throw new InvalidOperationException("simulated query failure");
/// <inheritdoc />
public Task<int> PurgeTerminalAsync(DateTime olderThanUtc, CancellationToken ct = default) =>
_inner.PurgeTerminalAsync(olderThanUtc, ct);
/// <inheritdoc />
public Task<SiteCallKpiSnapshot> ComputeKpisAsync(
DateTime stuckCutoff, DateTime intervalSince, CancellationToken ct = default) =>
_inner.ComputeKpisAsync(stuckCutoff, intervalSince, ct);
/// <inheritdoc />
public Task<IReadOnlyList<SiteCallSiteKpiSnapshot>> ComputePerSiteKpisAsync(
DateTime stuckCutoff, DateTime intervalSince, CancellationToken ct = default) =>
_inner.ComputePerSiteKpisAsync(stuckCutoff, intervalSince, ct);
/// <inheritdoc />
public Task<IReadOnlyList<SiteCallNodeKpiSnapshot>> ComputePerNodeKpisAsync(
DateTime stuckCutoff, DateTime intervalSince, CancellationToken ct = default) =>
_inner.ComputePerNodeKpisAsync(stuckCutoff, intervalSince, ct);
@@ -846,12 +893,16 @@ public class SiteCallAuditActorTests : TestKit, IClassFixture<MsSqlMigrationFixt
private readonly ISiteCallAuditRepository _inner;
private readonly TrackedOperationId _poisonId;
/// <summary>Initializes the repository wrapper.</summary>
/// <param name="inner">The real repository that non-poisoned calls delegate to.</param>
/// <param name="poisonId">The tracked operation id whose upsert throws.</param>
public ThrowingRepository(ISiteCallAuditRepository inner, TrackedOperationId poisonId)
{
_inner = inner;
_poisonId = poisonId;
}
/// <inheritdoc />
public Task UpsertAsync(SiteCall siteCall, CancellationToken ct = default)
{
if (siteCall.TrackedOperationId == _poisonId)
@@ -861,24 +912,30 @@ public class SiteCallAuditActorTests : TestKit, IClassFixture<MsSqlMigrationFixt
return _inner.UpsertAsync(siteCall, ct);
}
/// <inheritdoc />
public Task<SiteCall?> GetAsync(TrackedOperationId id, CancellationToken ct = default) =>
_inner.GetAsync(id, ct);
/// <inheritdoc />
public Task<IReadOnlyList<SiteCall>> QueryAsync(
SiteCallQueryFilter filter, SiteCallPaging paging, CancellationToken ct = default) =>
_inner.QueryAsync(filter, paging, ct);
/// <inheritdoc />
public Task<int> PurgeTerminalAsync(DateTime olderThanUtc, CancellationToken ct = default) =>
_inner.PurgeTerminalAsync(olderThanUtc, ct);
/// <inheritdoc />
public Task<SiteCallKpiSnapshot> ComputeKpisAsync(
DateTime stuckCutoff, DateTime intervalSince, CancellationToken ct = default) =>
_inner.ComputeKpisAsync(stuckCutoff, intervalSince, ct);
/// <inheritdoc />
public Task<IReadOnlyList<SiteCallSiteKpiSnapshot>> ComputePerSiteKpisAsync(
DateTime stuckCutoff, DateTime intervalSince, CancellationToken ct = default) =>
_inner.ComputePerSiteKpisAsync(stuckCutoff, intervalSince, ct);
/// <inheritdoc />
public Task<IReadOnlyList<SiteCallNodeKpiSnapshot>> ComputePerNodeKpisAsync(
DateTime stuckCutoff, DateTime intervalSince, CancellationToken ct = default) =>
_inner.ComputePerNodeKpisAsync(stuckCutoff, intervalSince, ct);