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:
+34
-20
@@ -10,7 +10,7 @@ using ZB.MOM.WW.ScadaBridge.HealthMonitoring;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.DataConnectionLayer.Tests;
|
||||
|
||||
/// <summary>Task-10: native alarm subscribe + source-ref routing + unavailable signal.</summary>
|
||||
/// <summary>Native alarm subscribe + source-ref routing + unavailable signal.</summary>
|
||||
public class DataConnectionActorAlarmTests : TestKit
|
||||
{
|
||||
private readonly ISiteHealthCollector _health = Substitute.For<ISiteHealthCollector>();
|
||||
@@ -44,6 +44,7 @@ public class DataConnectionActorAlarmTests : TestKit
|
||||
return (adapter, () => cb);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that an alarm subscription routes a transition to the instance subscriber.</summary>
|
||||
[Fact]
|
||||
public void SubscribeAlarms_RoutesTransitionToInstanceSubscriber()
|
||||
{
|
||||
@@ -67,10 +68,11 @@ public class DataConnectionActorAlarmTests : TestKit
|
||||
ExpectMsg<NativeAlarmTransitionUpdate>(u => u.Transition.SourceObjectReference == "Tank01");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that an alarm bound by node id routes its transition to the subscriber.</summary>
|
||||
[Fact]
|
||||
public void SubscribeAlarms_NodeIdBinding_RoutesTransition()
|
||||
{
|
||||
// Gitea #17 end-to-end: an instance binds a native alarm source by NodeId (the form
|
||||
// End-to-end: an instance binds a native alarm source by NodeId (the form
|
||||
// the picker / CSV / config store). The adapter builds the transition's identity via
|
||||
// OpcUaAlarmMapper.BuildIdentity(binding, SourceName, ConditionName). With the old
|
||||
// "SourceObjectReference = SourceName" logic the event's name ("pymodbus/plc/HR200")
|
||||
@@ -105,6 +107,7 @@ public class DataConnectionActorAlarmTests : TestKit
|
||||
Assert.Equal("pymodbus/plc/HR200.HR200", update.Transition.SourceReference);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that subscribing on an adapter that cannot raise alarms replies with a failure.</summary>
|
||||
[Fact]
|
||||
public void SubscribeAlarms_OnNonAlarmCapableAdapter_RepliesFailure()
|
||||
{
|
||||
@@ -119,6 +122,7 @@ public class DataConnectionActorAlarmTests : TestKit
|
||||
ExpectMsg<SubscribeAlarmsResponse>(m => !m.Success && m.ErrorMessage != null);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a second subscriber with a different filter logs an overwrite warning.</summary>
|
||||
[Fact]
|
||||
public void SecondAlarmSubscriber_WithDifferentFilter_LogsOverwriteWarning()
|
||||
{
|
||||
@@ -142,8 +146,9 @@ public class DataConnectionActorAlarmTests : TestKit
|
||||
});
|
||||
}
|
||||
|
||||
// ── M2.4 (#8): conditionFilter is now applied client-side in the actor ──
|
||||
// ── conditionFilter is now applied client-side in the actor ──
|
||||
|
||||
/// <summary>Verifies that a type filter delivers only matching alarm types.</summary>
|
||||
[Fact]
|
||||
public void SubscribeAlarms_WithTypeFilter_DeliversOnlyMatchingTypes()
|
||||
{
|
||||
@@ -166,6 +171,7 @@ public class DataConnectionActorAlarmTests : TestKit
|
||||
ExpectMsg<NativeAlarmTransitionUpdate>(u => u.Transition.AlarmTypeName == "AnalogLimit.Hi");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a null filter delivers all alarm types.</summary>
|
||||
[Fact]
|
||||
public void SubscribeAlarms_WithNullFilter_DeliversAllTypes()
|
||||
{
|
||||
@@ -184,6 +190,7 @@ public class DataConnectionActorAlarmTests : TestKit
|
||||
ExpectMsg<NativeAlarmTransitionUpdate>(u => u.Transition.AlarmTypeName == "DiscreteAlarm");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that filter matching ignores letter case and surrounding whitespace.</summary>
|
||||
[Fact]
|
||||
public void SubscribeAlarms_FilterMatch_IgnoresCaseAndWhitespace()
|
||||
{
|
||||
@@ -205,6 +212,7 @@ public class DataConnectionActorAlarmTests : TestKit
|
||||
ExpectNoMsg(TimeSpan.FromMilliseconds(250));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a gateway-wide alarm feed is filtered client-side.</summary>
|
||||
[Fact]
|
||||
public void SubscribeAlarms_GatewayWideFeed_IsFilteredClientSide()
|
||||
{
|
||||
@@ -234,6 +242,7 @@ public class DataConnectionActorAlarmTests : TestKit
|
||||
u.Transition.SourceObjectReference == "Reactor" && u.Transition.AlarmTypeName == "HighTemp");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a filtered subscription still forwards the snapshot-complete sentinel.</summary>
|
||||
[Fact]
|
||||
public void SubscribeAlarms_WithFilter_StillForwardsSnapshotCompleteSentinel()
|
||||
{
|
||||
@@ -257,6 +266,7 @@ public class DataConnectionActorAlarmTests : TestKit
|
||||
ExpectMsg<NativeAlarmTransitionUpdate>(u => u.Transition.Kind == AlarmTransitionKind.SnapshotComplete);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a real snapshot-complete marker with an empty reference is broadcast to a specific source.</summary>
|
||||
[Fact]
|
||||
public void SubscribeAlarms_RealEmptyRefSnapshotComplete_IsBroadcastToSpecificSource()
|
||||
{
|
||||
@@ -293,13 +303,15 @@ public class DataConnectionActorAlarmTests : TestKit
|
||||
ExpectMsg<NativeAlarmTransitionUpdate>(u => u.Transition.Kind == AlarmTransitionKind.SnapshotComplete);
|
||||
}
|
||||
|
||||
// ── DataConnectionLayer-023: mid-flight alarm unsubscribe must release the adapter feed ──
|
||||
// ── Mid-flight alarm unsubscribe must release the adapter feed ──
|
||||
|
||||
/// <summary>Verifies that unsubscribing during an in-flight alarm subscribe releases the adapter feed and leaves the actor state clean.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task DCL023_UnsubscribeDuringInFlightAlarmSubscribe_ReleasesAdapterFeed_AndKeepsStateClean()
|
||||
{
|
||||
// Regression test for DataConnectionLayer-023. Previously the native-alarm
|
||||
// subscribe path never inherited the DCL-021 obsolete-completion guard: if the
|
||||
// Regression test: previously the native-alarm
|
||||
// subscribe path never inherited the obsolete-completion guard: if the
|
||||
// last subscriber unsubscribed while the adapter alarm subscribe was in flight,
|
||||
// HandleUnsubscribeAlarms could not tear down the feed (the subscription id was
|
||||
// not stored yet), and the late AlarmSubscribeCompleted unconditionally stored
|
||||
@@ -368,20 +380,22 @@ public class DataConnectionActorAlarmTests : TestKit
|
||||
"Tank01", Arg.Any<string?>(), Arg.Any<AlarmTransitionCallback>(), Arg.Any<CancellationToken>());
|
||||
}
|
||||
|
||||
// ── DataConnectionLayer-029: a re-subscribe during an orphaned in-flight subscribe
|
||||
// ── A re-subscribe during an orphaned in-flight subscribe
|
||||
// must not leak a duplicate adapter feed ──
|
||||
|
||||
/// <summary>Verifies that a re-subscribe during an orphaned in-flight subscribe releases the duplicate feed without leaking.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task DCL029_ResubscribeDuringOrphanedInFlightSubscribe_ReleasesDuplicateFeed_NoLeak()
|
||||
{
|
||||
// Regression test for DataConnectionLayer-029. The DCL-023 fix clears the in-flight
|
||||
// Regression test: the mid-flight-unsubscribe fix clears the in-flight
|
||||
// marker on unsubscribe, which reopens a double-subscribe window: unsubscribe (last
|
||||
// subscriber, subId not stored yet) → a fresh subscribe for the SAME source sees
|
||||
// neither a stored id nor an in-flight marker, so it issues a SECOND adapter feed →
|
||||
// both completions fire. The DCL-023 orphan guard does NOT trigger on either
|
||||
// both completions fire. The orphan guard does NOT trigger on either
|
||||
// completion (the re-subscribe re-added the subscriber), so the alarm completion
|
||||
// handler used to OVERWRITE _alarmSubscriptionIds with the second id — leaking the
|
||||
// first feed (never unsubscribed, kept streaming). After DCL-029 the handler mirrors
|
||||
// first feed (never unsubscribed, kept streaming). With the fix the handler mirrors
|
||||
// the tag-path re-check: when a feed is already stored, the redundant completion
|
||||
// releases its just-created feed instead of overwriting + leaking.
|
||||
var sub1Started = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
@@ -413,35 +427,35 @@ public class DataConnectionActorAlarmTests : TestKit
|
||||
var actor = Sys.ActorOf(Props.Create(() => new DataConnectionActor(
|
||||
"conn", adapter, _options, _health, _factory, "OpcUa")));
|
||||
|
||||
// (1) Subscribe A — adapter subscribe #1 parks, in-flight={Tank01}.
|
||||
// (1) Subscribe A — the first adapter subscribe parks, in-flight={Tank01}.
|
||||
actor.Tell(new SubscribeAlarmsRequest("c1", "instA", "conn", "Tank01", null, DateTimeOffset.UtcNow));
|
||||
await sub1Started.Task.WaitAsync(TimeSpan.FromSeconds(5));
|
||||
|
||||
// (2) Last subscriber unsubscribes while subscribe #1 is in flight — clears the
|
||||
// in-flight marker (DCL-023); subId#1 is not stored yet so no teardown happens.
|
||||
// (2) Last subscriber unsubscribes while the first subscribe is in flight — clears the
|
||||
// in-flight marker; the first subscription id is not stored yet so no teardown happens.
|
||||
actor.Tell(new UnsubscribeAlarmsRequest("unsub-c1", "instA", "conn", "Tank01", DateTimeOffset.UtcNow));
|
||||
await Task.Delay(150);
|
||||
|
||||
// (3) Fresh subscribe for the SAME source before #1 completes — neither a stored id
|
||||
// (3) Fresh subscribe for the SAME source before the first completes — neither a stored id
|
||||
// nor an in-flight marker exists, so the actor issues a SECOND adapter subscribe.
|
||||
actor.Tell(new SubscribeAlarmsRequest("c2", "instB", "conn", "Tank01", null, DateTimeOffset.UtcNow));
|
||||
await sub2Started.Task.WaitAsync(TimeSpan.FromSeconds(5));
|
||||
|
||||
// (4) Complete subscribe #1 → a subscriber exists again (B re-added), so the orphan
|
||||
// guard does NOT fire and subId#1 is stored as the live feed.
|
||||
// (4) Complete the first subscribe → a subscriber exists again (B re-added), so the orphan
|
||||
// guard does NOT fire and its subscription id is stored as the live feed.
|
||||
sub1Release.SetResult("alarm-sub-1");
|
||||
await Task.Delay(150);
|
||||
|
||||
// (5) Complete subscribe #2 → a feed is already stored, so this redundant completion
|
||||
// releases its just-created feed (#2) instead of overwriting + leaking subId#1.
|
||||
// (5) Complete the second subscribe → a feed is already stored, so this redundant completion
|
||||
// releases its just-created feed instead of overwriting + leaking the first subscription id.
|
||||
sub2Release.SetResult("alarm-sub-2");
|
||||
await Task.Delay(300);
|
||||
|
||||
// The duplicate feed (#2) is released exactly once; the first feed (#1) is retained.
|
||||
// The duplicate (second) feed is released exactly once; the first feed is retained.
|
||||
await alarmable.Received(1).UnsubscribeAlarmsAsync("alarm-sub-2", Arg.Any<CancellationToken>());
|
||||
await alarmable.DidNotReceive().UnsubscribeAlarmsAsync("alarm-sub-1", Arg.Any<CancellationToken>());
|
||||
|
||||
// The retained feed (#1) is what a later unsubscribe tears down — proving subId#1,
|
||||
// The retained (first) feed is what a later unsubscribe tears down — proving the first subscription id,
|
||||
// not the duplicate, is the id _alarmSubscriptionIds actually tracks (no leak).
|
||||
actor.Tell(new UnsubscribeAlarmsRequest("unsub-c2", "instB", "conn", "Tank01", DateTimeOffset.UtcNow));
|
||||
await Task.Delay(200);
|
||||
|
||||
Reference in New Issue
Block a user