mbproxy: strip historical phase/wave/plan references from source comments
Comments described the *history* of how the code arrived (phase numbers, wave IDs, review IDs, dated TODOs) instead of what it does today. That scaffolding rotted as the codebase evolved. Cleaned 60 source files + .gitignore; behaviour unchanged (387/387 tests still pass). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -380,8 +380,8 @@ public sealed class PlcMultiplexerTests
|
||||
try
|
||||
{
|
||||
// Both clients use the same upstream TxId 0x0007 — the proxy must hand out
|
||||
// distinct proxy TxIds on the backend wire. Phase 10: reads target DIFFERENT
|
||||
// addresses so coalescing does not fuse them into a single backend request.
|
||||
// distinct proxy TxIds on the backend wire. Reads target DIFFERENT addresses
|
||||
// so coalescing does not fuse them into a single backend request.
|
||||
await c1.SendAsync(BuildFc03ReadFrame(0x0007, 0, 1), SocketFlags.None);
|
||||
await c2.SendAsync(BuildFc03ReadFrame(0x0007, 10, 1), SocketFlags.None);
|
||||
|
||||
@@ -625,12 +625,12 @@ public sealed class PlcMultiplexerTests
|
||||
}
|
||||
}
|
||||
|
||||
// ── Phase 12 Wave-1 regression tests ──────────────────────────────────────
|
||||
// ── ReplaceContext live-swap regression tests ────────────────────────────────
|
||||
|
||||
/// <summary>
|
||||
/// W1.1 — verifies that <see cref="PlcMultiplexer.ReplaceContext"/> swaps the live
|
||||
/// per-PLC context on the running multiplexer, so the very next PDU's BCD rewriter
|
||||
/// uses the new tag map (not the captured-at-construction map). Before W1.1 this
|
||||
/// Verifies that <see cref="PlcMultiplexer.ReplaceContext"/> swaps the live per-PLC
|
||||
/// context on the running multiplexer, so the very next PDU's BCD rewriter uses the
|
||||
/// new tag map (not the captured-at-construction map). Without the live swap this
|
||||
/// scenario would silently keep using the old map until the listener faulted and the
|
||||
/// supervisor's Polly loop reconstructed everything.
|
||||
/// </summary>
|
||||
@@ -682,11 +682,11 @@ public sealed class PlcMultiplexerTests
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// W1.1 — verifies that swapping in a fresh response cache via <see cref="PlcMultiplexer.ReplaceContext"/>
|
||||
/// makes the running multiplexer consult the NEW cache for subsequent reads, not the
|
||||
/// old cache that was disposed by the supervisor. Without W1.1 the running mux would
|
||||
/// keep its constructor-captured cache reference and either return stale entries or
|
||||
/// hit a disposed cache.
|
||||
/// Verifies that swapping in a fresh response cache via
|
||||
/// <see cref="PlcMultiplexer.ReplaceContext"/> makes the running multiplexer consult
|
||||
/// the NEW cache for subsequent reads, not the old cache that was disposed by the
|
||||
/// supervisor. Without the live swap the running mux would keep its constructor-
|
||||
/// captured cache reference and either return stale entries or hit a disposed cache.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task ReplaceContext_NewCache_NextReadGoesToBackend_NotOldCache()
|
||||
@@ -757,7 +757,7 @@ public sealed class PlcMultiplexerTests
|
||||
}
|
||||
}
|
||||
|
||||
// ── Phase 12 (W3 final-tier race tests) ──────────────────────────────────
|
||||
// ── Final-tier race tests ─────────────────────────────────────────────────
|
||||
|
||||
/// <summary>
|
||||
/// Reflection helper — drains the multiplexer's TxIdAllocator by calling
|
||||
@@ -781,10 +781,10 @@ public sealed class PlcMultiplexerTests
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// W3 #5 — TxId allocator saturation propagates as a Modbus exception 04 to the
|
||||
/// upstream client (no hang, no crash). The 16-bit TxId space (65,536 slots) is
|
||||
/// pre-saturated via reflection so the next request hits the
|
||||
/// <c>!_allocator.TryAllocate</c> branch in <c>OnUpstreamFrameAsync</c> immediately.
|
||||
/// TxId allocator saturation propagates as a Modbus exception 04 to the upstream
|
||||
/// client (no hang, no crash). The 16-bit TxId space (65,536 slots) is pre-saturated
|
||||
/// via reflection so the next request hits the <c>!_allocator.TryAllocate</c> branch
|
||||
/// in <c>OnUpstreamFrameAsync</c> immediately.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task TxIdAllocator_Saturated_NextRequest_GetsException04_WithOriginalTxId()
|
||||
@@ -835,11 +835,11 @@ public sealed class PlcMultiplexerTests
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// W3 #6 — under TxId saturation, two concurrent identical FC03 reads must BOTH
|
||||
/// receive exception 04 (one as the leader directly, the other either via a
|
||||
/// coalesced fan-out from the W1.2 cleanup OR via its own independent saturation
|
||||
/// path — either timing produces the same observable contract). Validates that no
|
||||
/// pipe hangs forever waiting for a backend response that would never arrive.
|
||||
/// Under TxId saturation, two concurrent identical FC03 reads must BOTH receive
|
||||
/// exception 04 (one as the leader directly, the other either via a coalesced
|
||||
/// fan-out from the saturation cleanup OR via its own independent saturation path —
|
||||
/// either timing produces the same observable contract). Validates that no pipe
|
||||
/// hangs forever waiting for a backend response that would never arrive.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task TxIdAllocator_Saturated_TwoConcurrentIdenticalReads_BothPipesGetException04()
|
||||
@@ -877,7 +877,7 @@ public sealed class PlcMultiplexerTests
|
||||
var rspA = await ReadOneFrameAsync(cA, TestContext.Current.CancellationToken);
|
||||
var rspB = await ReadOneFrameAsync(cB, TestContext.Current.CancellationToken);
|
||||
|
||||
// Both must be exception 04 with the original TxId echoed — the W1.2 contract
|
||||
// Both must be exception 04 with the original TxId echoed — the contract
|
||||
// is "no late attacher hangs."
|
||||
foreach (var (rsp, expectedTxId, label) in new[] {
|
||||
(rspA, txA, "A"), (rspB, txB, "B") })
|
||||
@@ -898,14 +898,14 @@ public sealed class PlcMultiplexerTests
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// W3 #7 — backend-reader head-of-line block. One upstream pipe is wedged by the
|
||||
/// test holding its socket-receive side without reading. The W1.3 fix routes the
|
||||
/// fan-out through <c>TrySendResponse</c> so the per-PLC backend reader cannot be
|
||||
/// stalled by a wedged pipe; responses to a healthy peer must keep flowing and the
|
||||
/// wedged pipe's <c>responseDropForFullUpstream</c> counter must increment.
|
||||
/// Backend-reader head-of-line block guard. One upstream pipe is wedged by the test
|
||||
/// holding its socket-receive side without reading. The fan-out is routed through
|
||||
/// <c>TrySendResponse</c> so the per-PLC backend reader cannot be stalled by a
|
||||
/// wedged pipe; responses to a healthy peer must keep flowing and the wedged pipe's
|
||||
/// <c>responseDropForFullUpstream</c> counter must increment.
|
||||
///
|
||||
/// <para>Pre-W1.3 the synchronous <c>await SendResponseAsync</c> inside the reader
|
||||
/// would block on the wedged pipe's full bounded channel and starve every peer.</para>
|
||||
/// <para>A synchronous <c>await SendResponseAsync</c> inside the reader would block
|
||||
/// on the wedged pipe's full bounded channel and starve every peer.</para>
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task SlowUpstream_DoesNotStallPeerResponses_DropCounterIncrements()
|
||||
@@ -943,8 +943,8 @@ public sealed class PlcMultiplexerTests
|
||||
await cB.SendAsync(BuildFc03ReadFrame(txB, 0, 1), SocketFlags.None);
|
||||
|
||||
// B's response must arrive within a few hundred ms even with A wedged. If
|
||||
// the W1.3 fix were missing, the reader would be blocked on A's channel and
|
||||
// B would time out.
|
||||
// the non-blocking enqueue path were missing, the reader would be blocked on
|
||||
// A's channel and B would time out.
|
||||
var rspB = await ReadOneFrameAsync(cB, TestContext.Current.CancellationToken)
|
||||
.WaitAsync(TimeSpan.FromSeconds(3), TestContext.Current.CancellationToken);
|
||||
ushort echoB = (ushort)((rspB[0] << 8) | rspB[1]);
|
||||
@@ -972,7 +972,7 @@ public sealed class PlcMultiplexerTests
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// W3 #8 — watchdog↔response race. The W1 design uses claim-then-dispatch:
|
||||
/// Watchdog↔response race. The design uses claim-then-dispatch:
|
||||
/// <c>CorrelationMap.TryRemove</c> is the single source of truth, so exactly ONE
|
||||
/// of (response delivered, watchdog timeout) wins for any given proxy TxId. This
|
||||
/// test exercises the race window directly: a stub backend that responds at almost
|
||||
@@ -992,13 +992,13 @@ public sealed class PlcMultiplexerTests
|
||||
// = 400 the tick is 100 ms. Configure the backend to delay 350-450 ms for each
|
||||
// request so some land before, some after the timeout.
|
||||
int backendPort = PickFreePort();
|
||||
// Phase 12 (W4 / T2) — deterministic alternation rather than seeded Random. Random
|
||||
// with a fixed seed is not stable across .NET major versions (Microsoft has changed
|
||||
// the implementation, e.g. legacy → Xoshiro128 in .NET 6), so a runtime upgrade
|
||||
// could land all samples on one side of the watchdog deadline and break the
|
||||
// "both branches must fire" assertion below. Counter-based alternation guarantees
|
||||
// 15 fast (350 ms, beats watchdog) and 15 slow (450 ms, loses to watchdog) responses
|
||||
// across 30 iterations, regardless of runtime.
|
||||
// Deterministic alternation rather than seeded Random. Random with a fixed seed is
|
||||
// not stable across .NET major versions (Microsoft has changed the implementation,
|
||||
// e.g. legacy → Xoshiro128 in .NET 6), so a runtime upgrade could land all samples
|
||||
// on one side of the watchdog deadline and break the "both branches must fire"
|
||||
// assertion below. Counter-based alternation guarantees 15 fast (350 ms, beats
|
||||
// watchdog) and 15 slow (450 ms, loses to watchdog) responses across 30 iterations,
|
||||
// regardless of runtime.
|
||||
int reqCount = 0;
|
||||
var slowBackend = new SlowResponseBackend(backendPort, () =>
|
||||
{
|
||||
@@ -1062,13 +1062,13 @@ public sealed class PlcMultiplexerTests
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// W3 #9 — cascade racing with new accepts. Stress-test: while the backend is repeatedly
|
||||
/// Cascade racing with new accepts. Stress-test: while the backend is repeatedly
|
||||
/// killed and resurrected (forcing repeated cascade cycles), new upstream clients
|
||||
/// connect and disconnect concurrently. The contract verified is the
|
||||
/// no-crash-under-churn property: the multiplexer must survive arbitrary interleavings
|
||||
/// of teardown and new-pipe-attach without throwing into the host or leaking sockets.
|
||||
///
|
||||
/// <para>The originally-flagged race window — a new pipe added between
|
||||
/// <para>The race window — a new pipe added between
|
||||
/// <c>_pipes.Values.ToArray()</c> and <c>_pipes.Clear()</c> in <c>TearDownBackendAsync</c>
|
||||
/// — leaves the new pipe alive but orphaned from <c>_pipes</c>. Its read loop will
|
||||
/// receive normal traffic until the next cascade or its socket closes. This test
|
||||
@@ -1165,7 +1165,7 @@ public sealed class PlcMultiplexerTests
|
||||
|
||||
/// <summary>
|
||||
/// Backend stub that delays each response by a caller-supplied amount. Used by the
|
||||
/// W3 #8 watchdog race test.
|
||||
/// watchdog-vs-response race test.
|
||||
/// </summary>
|
||||
private sealed class SlowResponseBackend : IAsyncDisposable
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user