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:
+73
-23
@@ -25,6 +25,7 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
private const string GrpcNodeA = "http://localhost:5100";
|
||||
private const string GrpcNodeB = "http://localhost:5200";
|
||||
|
||||
/// <summary>Initializes the test class with a short-timeout Akka configuration.</summary>
|
||||
public DebugStreamBridgeActorTests() : base(@"akka.loglevel = DEBUG")
|
||||
{
|
||||
// Use a very short reconnect delay for testing
|
||||
@@ -67,10 +68,11 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
return new TestContext(actor, commProbe, mockClient, events, terminated);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that an instance-not-found snapshot is forwarded to the event callback, tears down the stream and terminates the actor.</summary>
|
||||
[Fact]
|
||||
public void On_InstanceNotFound_Snapshot_Forwards_To_OnEvent_Tears_Down_Stream_And_Terminates()
|
||||
{
|
||||
// M2.11 (revised for M2.18 stream-first): the gRPC subscription is now opened
|
||||
// Stream-first: the gRPC subscription is now opened
|
||||
// up-front in PreStart, so when the site reports InstanceNotFound=true the
|
||||
// bridge actor must
|
||||
// (a) forward the not-found snapshot to _onEvent so DebugStreamService's TCS
|
||||
@@ -111,6 +113,7 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
ExpectTerminated(ctx.BridgeActor, TimeSpan.FromSeconds(3));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that PreStart sends a subscribe debug view request through the communication actor.</summary>
|
||||
[Fact]
|
||||
public void PreStart_Sends_SubscribeDebugViewRequest_Via_ClusterClient()
|
||||
{
|
||||
@@ -125,6 +128,7 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
Assert.Equal("corr-1", req.CorrelationId);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a snapshot is forwarded to the event callback.</summary>
|
||||
[Fact]
|
||||
public void On_Snapshot_Forwards_To_OnEvent_Callback()
|
||||
{
|
||||
@@ -144,10 +148,11 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
lock (ctx.ReceivedEvents) { Assert.IsType<DebugViewSnapshot>(ctx.ReceivedEvents[0]); }
|
||||
}
|
||||
|
||||
/// <summary>Verifies that receiving a snapshot does not open an additional gRPC stream.</summary>
|
||||
[Fact]
|
||||
public void On_Snapshot_Does_Not_Open_Additional_GrpcStream()
|
||||
{
|
||||
// M2.18 stream-first: the gRPC subscription is opened in PreStart, BEFORE the
|
||||
// Stream-first: the gRPC subscription is opened in PreStart, BEFORE the
|
||||
// snapshot arrives. After the snapshot is delivered the actor switches to
|
||||
// pass-through — it must NOT open a second subscription. Exactly ONE subscribe
|
||||
// call should have been made (the PreStart one).
|
||||
@@ -173,6 +178,7 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
Assert.Equal(InstanceName, singleCall.InstanceUniqueName);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that events from the gRPC callback are forwarded to the event callback.</summary>
|
||||
[Fact]
|
||||
public void Events_From_GrpcCallback_Forwarded_To_OnEvent()
|
||||
{
|
||||
@@ -198,6 +204,7 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
lock (ctx.ReceivedEvents) { Assert.IsType<AttributeValueChanged>(ctx.ReceivedEvents[1]); }
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a gRPC error causes a reconnect to the other node.</summary>
|
||||
[Fact]
|
||||
public void On_GrpcError_Reconnects_To_Other_Node()
|
||||
{
|
||||
@@ -221,10 +228,11 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
Assert.Equal("corr-1", ctx.MockGrpcClient.SubscribeCalls[1].CorrelationId);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a gRPC error unsubscribes the old stream before reconnecting.</summary>
|
||||
[Fact]
|
||||
public void On_GrpcError_Unsubscribes_Old_Stream_Before_Reconnect()
|
||||
{
|
||||
// Communication-002 regression: a reconnect must unsubscribe the previous
|
||||
// Regression: a reconnect must unsubscribe the previous
|
||||
// stream so the old node does not keep a zombie relay actor / subscription.
|
||||
var ctx = CreateBridgeActor();
|
||||
ctx.CommProbe.ExpectMsg<SiteEnvelope>();
|
||||
@@ -249,6 +257,7 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
Assert.Contains("corr-1", ctx.MockGrpcClient.UnsubscribedCorrelationIds);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the actor terminates after the maximum number of retries.</summary>
|
||||
[Fact]
|
||||
public void After_MaxRetries_Terminates()
|
||||
{
|
||||
@@ -282,6 +291,7 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
Assert.True(ctx.TerminatedFlag[0]);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that stopping the debug stream cancels the gRPC subscription and sends an unsubscribe.</summary>
|
||||
[Fact]
|
||||
public void StopDebugStream_Cancels_Grpc_And_Sends_Unsubscribe()
|
||||
{
|
||||
@@ -312,6 +322,7 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
ExpectTerminated(ctx.BridgeActor);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a debug stream terminated message stops the actor idempotently.</summary>
|
||||
[Fact]
|
||||
public void DebugStreamTerminated_Stops_Actor_Idempotently()
|
||||
{
|
||||
@@ -325,10 +336,11 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
Assert.True(ctx.TerminatedFlag[0]);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a flapping stream that delivers events between failures still terminates after the maximum retries.</summary>
|
||||
[Fact]
|
||||
public void FlappingStream_DeliveringEventsBetweenFailures_StillTerminatesAfterMaxRetries()
|
||||
{
|
||||
// Communication-008 regression: a stream that connects, delivers an event,
|
||||
// Regression: a stream that connects, delivers an event,
|
||||
// then fails — repeatedly — must still trip MaxRetries. The retry count is
|
||||
// NO LONGER reset by a received event (only by the stability window). The
|
||||
// previous behaviour reset _retryCount on every event, so a flapping site
|
||||
@@ -367,10 +379,11 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
Assert.True(ctx.TerminatedFlag[0]);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a gRPC error reconnects through a client bound to the other node's endpoint.</summary>
|
||||
[Fact]
|
||||
public void On_GrpcError_Reconnects_To_Other_Node_Endpoint()
|
||||
{
|
||||
// Communication-015 regression: drive the bridge actor through a node flip
|
||||
// Regression: drive the bridge actor through a node flip
|
||||
// with an endpoint-aware factory (one distinct mock client per endpoint).
|
||||
// The first subscribe targets NodeA; after a gRPC error the bridge must
|
||||
// reconnect via a client bound to the *NodeB* endpoint.
|
||||
@@ -407,8 +420,9 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
Assert.Equal("corr-1", factory.ClientFor(GrpcNodeB).SubscribeCalls[0].CorrelationId);
|
||||
}
|
||||
|
||||
// ── WP1.1: graceful (status OK) stream completion is a reconnect trigger ──
|
||||
// ── graceful (status OK) stream completion is a reconnect trigger ──
|
||||
|
||||
/// <summary>Verifies that a graceful stream completion reopens the stream on the same node.</summary>
|
||||
[Fact]
|
||||
public void On_GracefulStreamCompletion_Reopens_On_The_Same_Node()
|
||||
{
|
||||
@@ -429,6 +443,7 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
Assert.Contains("corr-1", factory.ClientFor(GrpcNodeA).UnsubscribedCorrelationIds);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that repeated graceful completions do not consume the error retry budget.</summary>
|
||||
[Fact]
|
||||
public void RepeatedGracefulCompletions_DoNotConsume_TheErrorRetryBudget()
|
||||
{
|
||||
@@ -449,6 +464,7 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
Assert.False(ctx.TerminatedFlag[0]);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a late completion from a previous stream generation is ignored.</summary>
|
||||
[Fact]
|
||||
public void LateCompletionFromAPreviousStreamGeneration_IsIgnored()
|
||||
{
|
||||
@@ -461,14 +477,14 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
AwaitCondition(() => factory.ClientFor(GrpcNodeB).SubscribeCalls.Count == 1,
|
||||
TimeSpan.FromSeconds(5));
|
||||
|
||||
// A completion racing out of the dead gen-1 stream must not tear down the live one.
|
||||
// A completion racing out of the dead first-generation stream must not tear down the live one.
|
||||
firstSub.OnCompleted();
|
||||
Thread.Sleep(300);
|
||||
Assert.DoesNotContain("corr-1", factory.ClientFor(GrpcNodeB).UnsubscribedCorrelationIds);
|
||||
Assert.Single(factory.ClientFor(GrpcNodeB).SubscribeCalls);
|
||||
}
|
||||
|
||||
// ── Task 6 (arch review 02, High): teardown/failover unsubscribe is endpoint-safe ──
|
||||
// ── teardown/failover unsubscribe is endpoint-safe ──
|
||||
// Both paths use TryGet, never GetOrCreate, so cleanup can never open a fresh
|
||||
// channel or (with (site,endpoint) keying) touch another session's channel.
|
||||
|
||||
@@ -485,6 +501,7 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
return (actor, factory);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that gRPC cleanup unsubscribes through TryGet without opening a channel.</summary>
|
||||
[Fact]
|
||||
public void CleanupGrpc_UnsubscribesViaTryGet_WithoutOpeningAChannel()
|
||||
{
|
||||
@@ -501,6 +518,7 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
Assert.Equal(createdBefore, factory.CreatedCount);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a session failover unsubscribes the failed endpoint through TryGet and opens only the reconnect channel.</summary>
|
||||
[Fact]
|
||||
public void SessionFailover_UnsubscribesFailedEndpointViaTryGet_OpensOnlyTheReconnectChannel()
|
||||
{
|
||||
@@ -523,13 +541,14 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// M2.18 (#26) — stream-first + replay/dedup
|
||||
// Stream-first + replay/dedup
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/// <summary>Verifies that PreStart opens the gRPC stream before the snapshot arrives.</summary>
|
||||
[Fact]
|
||||
public void PreStart_Opens_GrpcStream_Before_Snapshot_Arrives()
|
||||
{
|
||||
// M2.18: the gRPC subscription must be opened in PreStart (stream-first),
|
||||
// Stream-first: the gRPC subscription must be opened in PreStart (stream-first),
|
||||
// BEFORE the snapshot is delivered, so live events start flowing during the
|
||||
// snapshot-build + network-transit window. The old lifecycle opened the
|
||||
// stream only after the snapshot arrived, losing gap-window events.
|
||||
@@ -545,10 +564,11 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
lock (ctx.ReceivedEvents) { Assert.Empty(ctx.ReceivedEvents); }
|
||||
}
|
||||
|
||||
/// <summary>Verifies that an event buffered in the gap window before the snapshot is delivered exactly once after the snapshot.</summary>
|
||||
[Fact]
|
||||
public void GapWindow_Event_Buffered_Before_Snapshot_Is_Delivered_Exactly_Once_After_Snapshot()
|
||||
{
|
||||
// M2.18: an event arriving DURING the snapshot window (before the snapshot
|
||||
// An event arriving DURING the snapshot window (before the snapshot
|
||||
// is delivered) is buffered, then flushed exactly once AFTER the snapshot.
|
||||
var ctx = CreateBridgeActor();
|
||||
ctx.CommProbe.ExpectMsg<SiteEnvelope>();
|
||||
@@ -581,10 +601,11 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a buffered event already reflected in the snapshot is dropped.</summary>
|
||||
[Fact]
|
||||
public void Buffered_Event_Already_Reflected_In_Snapshot_Is_Dropped()
|
||||
{
|
||||
// M2.18 dedup: a buffered event whose entity is in the snapshot with an equal
|
||||
// Dedup: a buffered event whose entity is in the snapshot with an equal
|
||||
// or newer snapshot timestamp (buffered.Timestamp <= snapshot.Timestamp) is
|
||||
// already reflected and must be DROPPED.
|
||||
var ctx = CreateBridgeActor();
|
||||
@@ -618,10 +639,11 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a buffered event strictly newer than the snapshot entity is delivered.</summary>
|
||||
[Fact]
|
||||
public void Buffered_Event_Strictly_Newer_Than_Snapshot_Entity_Is_Delivered()
|
||||
{
|
||||
// M2.18 dedup: a buffered event strictly newer than the snapshot's entry for
|
||||
// Dedup: a buffered event strictly newer than the snapshot's entry for
|
||||
// the same entity (buffered.Timestamp > snapshot.Timestamp) is NOT a dup and
|
||||
// must be DELIVERED after the snapshot.
|
||||
var ctx = CreateBridgeActor();
|
||||
@@ -655,10 +677,11 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that buffered alarm deduplication uses the alarm identity and timestamp.</summary>
|
||||
[Fact]
|
||||
public void Buffered_Alarm_Dedup_Uses_AlarmIdentity_And_Timestamp()
|
||||
{
|
||||
// M2.18 dedup for alarms: identity = (instance, alarm name, source reference).
|
||||
// Dedup for alarms: identity = (instance, alarm name, source reference).
|
||||
// A buffered alarm older-or-equal to the snapshot's same-identity alarm is
|
||||
// dropped; a strictly-newer one is delivered.
|
||||
var ctx = CreateBridgeActor();
|
||||
@@ -701,10 +724,11 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that buffered events are flushed in arrival order.</summary>
|
||||
[Fact]
|
||||
public void Buffered_Events_Flushed_In_Arrival_Order()
|
||||
{
|
||||
// M2.18: ordering preserved across multiple buffered events (none are dups —
|
||||
// Ordering preserved across multiple buffered events (none are dups —
|
||||
// their entities are absent from the snapshot).
|
||||
var ctx = CreateBridgeActor();
|
||||
ctx.CommProbe.ExpectMsg<SiteEnvelope>();
|
||||
@@ -735,10 +759,11 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that after the flush the actor passes subsequent events through immediately.</summary>
|
||||
[Fact]
|
||||
public void PassThrough_After_Flush_Delivers_Subsequent_Events_Immediately()
|
||||
{
|
||||
// M2.18: after the snapshot+flush the actor switches to pass-through — later
|
||||
// After the snapshot+flush the actor switches to pass-through — later
|
||||
// events go straight to _onEvent (no buffering, no dup).
|
||||
var ctx = CreateBridgeActor();
|
||||
ctx.CommProbe.ExpectMsg<SiteEnvelope>();
|
||||
@@ -767,10 +792,11 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that an instance-not-found snapshot after the stream was opened first tears down the stream and does not enter pass-through.</summary>
|
||||
[Fact]
|
||||
public void InstanceNotFound_After_StreamFirst_Tears_Down_Stream_And_Does_Not_PassThrough()
|
||||
{
|
||||
// M2.18 + M2.11: stream-first means the gRPC subscription is already open
|
||||
// Stream-first means the gRPC subscription is already open
|
||||
// when an InstanceNotFound snapshot arrives. The bridge must tear that stream
|
||||
// down (Unsubscribe the just-opened correlation), deliver the not-found
|
||||
// snapshot, NOT enter pass-through, and stop cleanly.
|
||||
@@ -812,10 +838,11 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
lock (ctx.ReceivedEvents) { Assert.Single(ctx.ReceivedEvents); }
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a reconnect during the buffering phase keeps buffering until the snapshot arrives.</summary>
|
||||
[Fact]
|
||||
public void Reconnect_During_Buffering_Phase_Keeps_Buffering_Until_Snapshot()
|
||||
{
|
||||
// M2.18: a gRPC error/reconnect BEFORE the snapshot arrives must remain in the
|
||||
// A gRPC error/reconnect BEFORE the snapshot arrives must remain in the
|
||||
// buffering phase — events on the new stream are still buffered, then flushed
|
||||
// when the snapshot finally arrives.
|
||||
var ctx = CreateBridgeActor();
|
||||
@@ -849,10 +876,11 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a reconnect after the snapshot resumes pass-through rather than buffering.</summary>
|
||||
[Fact]
|
||||
public void Reconnect_After_Snapshot_Resumes_PassThrough_Not_Buffering()
|
||||
{
|
||||
// M2.18: a mid-session reconnect (after the snapshot was already delivered)
|
||||
// A mid-session reconnect (after the snapshot was already delivered)
|
||||
// must resume pass-through — the snapshot is a one-time thing and events on
|
||||
// the reconnected stream are delivered immediately, not re-buffered.
|
||||
var ctx = CreateBridgeActor();
|
||||
@@ -885,10 +913,11 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the retry count is recovered only after the stream stays stable for the stability window.</summary>
|
||||
[Fact]
|
||||
public void RetryCount_RecoveredOnlyAfterStreamStaysStableForStabilityWindow()
|
||||
{
|
||||
// Communication-008: after a stream has been connected for the stability
|
||||
// After a stream has been connected for the stability
|
||||
// window, the retry budget is recovered — a later transient fault then gets
|
||||
// a fresh set of retries rather than being counted against the old budget.
|
||||
DebugStreamBridgeActor.StabilityWindow = TimeSpan.FromMilliseconds(300);
|
||||
@@ -928,8 +957,9 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
}
|
||||
}
|
||||
|
||||
// ── WP2.3: bounded pre-snapshot buffer, hard snapshot deadline, timeout hygiene ──
|
||||
// ── bounded pre-snapshot buffer, hard snapshot deadline, timeout hygiene ──
|
||||
|
||||
/// <summary>Verifies that the pre-snapshot buffer is capped, drops the oldest events and counts the drops.</summary>
|
||||
[Fact]
|
||||
public void PreSnapshotBuffer_IsCapped_DropsOldest_AndCountsTheDrops()
|
||||
{
|
||||
@@ -986,6 +1016,7 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
}, TimeSpan.FromSeconds(10));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a missing snapshot within the deadline fails the session instead of buffering forever.</summary>
|
||||
[Fact]
|
||||
public void NoSnapshotWithinDeadline_FailsTheSession_InsteadOfBufferingForever()
|
||||
{
|
||||
@@ -1013,6 +1044,7 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the arrival of the snapshot stands down the deadline.</summary>
|
||||
[Fact]
|
||||
public void SnapshotArrival_StandsDownTheDeadline()
|
||||
{
|
||||
@@ -1048,6 +1080,7 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that stream events still reach the consumer through the wrapped callback path.</summary>
|
||||
[Fact]
|
||||
public void StreamEvents_StillReachTheConsumer_ThroughTheWrappedCallbackPath()
|
||||
{
|
||||
@@ -1076,6 +1109,7 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
|
||||
// ----- Orphan net: measures the CONSUMER, not the mailbox ----- //
|
||||
|
||||
/// <summary>Verifies that a healthy session streaming events with consumer keepalives survives well past the orphan window.</summary>
|
||||
[Fact]
|
||||
public void HealthySession_StreamingEvents_WithConsumerKeepalives_SurvivesWellPastTheOrphanWindow()
|
||||
{
|
||||
@@ -1132,6 +1166,7 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that an orphaned session whose consumer is gone still terminates even while events keep arriving.</summary>
|
||||
[Fact]
|
||||
public void OrphanedSession_ConsumerGone_StillTerminates_EvenWhileEventsKeepArriving()
|
||||
{
|
||||
@@ -1173,6 +1208,7 @@ public class DebugStreamBridgeActorTests : TestKit
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a consumer keepalive renews the orphan window after a near miss.</summary>
|
||||
[Fact]
|
||||
public void ConsumerKeepalive_RenewsTheWindow_AfterANearMiss()
|
||||
{
|
||||
@@ -1227,10 +1263,12 @@ internal class MockSiteStreamGrpcClient : SiteStreamGrpcClient
|
||||
|
||||
private MockSiteStreamGrpcClient(bool _) : base() { }
|
||||
|
||||
/// <summary>Initializes a mock client that records subscribe and unsubscribe calls.</summary>
|
||||
public MockSiteStreamGrpcClient() : base()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Task SubscribeAsync(
|
||||
string correlationId,
|
||||
string instanceUniqueName,
|
||||
@@ -1249,6 +1287,7 @@ internal class MockSiteStreamGrpcClient : SiteStreamGrpcClient
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Unsubscribe(string correlationId)
|
||||
{
|
||||
lock (_lock) { _unsubscribedCorrelationIds.Add(correlationId); }
|
||||
@@ -1269,14 +1308,18 @@ internal record MockSubscription(
|
||||
internal class MockSiteStreamGrpcClientFactory : SiteStreamGrpcClientFactory
|
||||
{
|
||||
private readonly MockSiteStreamGrpcClient _mockClient;
|
||||
/// <summary>Gets the endpoints requested through <c>GetOrCreate</c>, in call order.</summary>
|
||||
public List<string> RequestedEndpoints { get; } = new();
|
||||
|
||||
/// <summary>Initializes the factory with the mock client it always returns.</summary>
|
||||
/// <param name="mockClient">The mock client returned for every endpoint.</param>
|
||||
public MockSiteStreamGrpcClientFactory(MockSiteStreamGrpcClient mockClient)
|
||||
: base(Microsoft.Extensions.Logging.Abstractions.NullLoggerFactory.Instance)
|
||||
{
|
||||
_mockClient = mockClient;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override SiteStreamGrpcClient GetOrCreate(string siteIdentifier, string grpcEndpoint)
|
||||
{
|
||||
RequestedEndpoints.Add(grpcEndpoint);
|
||||
@@ -1285,7 +1328,8 @@ internal class MockSiteStreamGrpcClientFactory : SiteStreamGrpcClientFactory
|
||||
|
||||
// Mirrors the real factory's TryGet: returns the client only for an endpoint
|
||||
// already opened via GetOrCreate, never creating one. Lets teardown/failover
|
||||
// unsubscribe paths (now TryGet-based, Task 6) resolve the mock client.
|
||||
// unsubscribe paths (now TryGet-based) resolve the mock client.
|
||||
/// <inheritdoc />
|
||||
public override SiteStreamGrpcClient? TryGet(string siteIdentifier, string grpcEndpoint)
|
||||
=> RequestedEndpoints.Contains(grpcEndpoint) ? _mockClient : null;
|
||||
}
|
||||
@@ -1293,27 +1337,33 @@ internal class MockSiteStreamGrpcClientFactory : SiteStreamGrpcClientFactory
|
||||
/// <summary>
|
||||
/// Endpoint-aware mock factory: hands out a distinct <see cref="MockSiteStreamGrpcClient"/>
|
||||
/// per endpoint, mirroring the real factory's corrected NodeA→NodeB failover behaviour
|
||||
/// so node-flip coverage is meaningful (Communication-015).
|
||||
/// so node-flip coverage is meaningful.
|
||||
/// </summary>
|
||||
internal class EndpointTrackingGrpcClientFactory : SiteStreamGrpcClientFactory
|
||||
{
|
||||
private readonly System.Collections.Concurrent.ConcurrentDictionary<string, MockSiteStreamGrpcClient> _byEndpoint = new();
|
||||
|
||||
/// <summary>Initializes an empty endpoint-aware factory.</summary>
|
||||
public EndpointTrackingGrpcClientFactory()
|
||||
: base(Microsoft.Extensions.Logging.Abstractions.NullLoggerFactory.Instance)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Gets the mock client bound to an endpoint, creating it on first use.</summary>
|
||||
/// <param name="endpoint">The gRPC endpoint address.</param>
|
||||
/// <returns>The mock client for the endpoint.</returns>
|
||||
public MockSiteStreamGrpcClient ClientFor(string endpoint) =>
|
||||
_byEndpoint.GetOrAdd(endpoint, _ => new MockSiteStreamGrpcClient());
|
||||
|
||||
/// <summary>Number of distinct endpoint clients created so far (channels opened).</summary>
|
||||
public int CreatedCount => _byEndpoint.Count;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override SiteStreamGrpcClient GetOrCreate(string siteIdentifier, string grpcEndpoint)
|
||||
=> ClientFor(grpcEndpoint);
|
||||
|
||||
// TryGet never creates: returns the client only for an already-opened endpoint.
|
||||
/// <inheritdoc />
|
||||
public override SiteStreamGrpcClient? TryGet(string siteIdentifier, string grpcEndpoint)
|
||||
=> _byEndpoint.TryGetValue(grpcEndpoint, out var client) ? client : null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user