docs: complete XML doc comments via fixdocs (2757 to 131 findings)

Add missing <returns>/<param>/<summary>/<typeparam> tags and clean up
misused inheritdoc across 481 files so the documented API surface is
complete. Documentation-only (zero code lines changed). The 131 remaining
findings are inheritdoc-style warnings deliberately left to preserve
hand-written implementation rationale (plan-decision notes, race-condition
explanations).
This commit is contained in:
Joseph Doherty
2026-06-03 12:34:34 -04:00
parent c6d9b20d9f
commit bd6c0b4d3d
481 changed files with 2550 additions and 1668 deletions
@@ -12,11 +12,7 @@ internal sealed class FakeEndpointDiscovery : IEndpointDiscovery
/// <summary>Gets the last endpoint URL passed to SelectEndpoint.</summary>
public string? LastEndpointUrl { get; private set; }
/// <summary>Selects an endpoint for the given configuration and URL, optionally throwing an exception.</summary>
/// <param name="config">The application configuration.</param>
/// <param name="endpointUrl">The endpoint URL to select.</param>
/// <param name="requestedMode">The requested security mode.</param>
/// <returns>The selected endpoint description.</returns>
/// <inheritdoc />
public EndpointDescription SelectEndpoint(ApplicationConfiguration config, string endpointUrl,
MessageSecurityMode requestedMode)
{
@@ -44,6 +44,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that a valid connection request returns populated connection metadata and marks the client as connected.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ConnectAsync_ValidSettings_ReturnsConnectionInfo()
{
@@ -58,6 +59,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that invalid connection settings fail validation before any OPC UA session is created.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ConnectAsync_InvalidSettings_ThrowsBeforeCreatingSession()
{
@@ -71,6 +73,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that server and security details from the session are copied into the exposed connection info.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ConnectAsync_PopulatesConnectionInfo()
{
@@ -96,6 +99,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that connection-state transitions are raised for the connecting and connected phases.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ConnectAsync_RaisesConnectionStateChangedEvents()
{
@@ -114,6 +118,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that a failed session creation leaves the client in the disconnected state.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ConnectAsync_SessionFactoryFails_TransitionsToDisconnected()
{
@@ -130,6 +135,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that username and password settings are passed through to the session-creation pipeline.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ConnectAsync_WithUsername_PassesThroughToFactory()
{
@@ -148,6 +154,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that disconnect closes the active session and clears exposed connection state.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task DisconnectAsync_WhenConnected_ClosesSession()
{
@@ -164,6 +171,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that disconnect is safe to call when no server session is active.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task DisconnectAsync_WhenNotConnected_IsIdempotent()
{
@@ -174,6 +182,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that repeated disconnect calls do not throw after cleanup has already run.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task DisconnectAsync_CalledTwice_IsIdempotent()
{
@@ -187,6 +196,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that a connected client can read the current value of a node through the session adapter.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ReadValueAsync_WhenConnected_ReturnsValue()
{
@@ -206,6 +216,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that reads are rejected when the client is not connected to a server.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ReadValueAsync_WhenDisconnected_Throws()
{
@@ -216,6 +227,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that session-level read failures are surfaced to callers instead of being swallowed.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task ReadValueAsync_SessionThrows_PropagatesException()
{
@@ -232,6 +244,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that writes succeed through the session adapter when the client is connected.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task WriteValueAsync_WhenConnected_WritesValue()
{
@@ -252,6 +265,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that string inputs are coerced to the node's current data type before writing.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task WriteValueAsync_StringValue_CoercesToTargetType()
{
@@ -271,6 +285,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that non-string values are written directly without an extra type-inference read.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task WriteValueAsync_NonStringValue_WritesDirectly()
{
@@ -287,6 +302,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that writes are rejected when the client is disconnected.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task WriteValueAsync_WhenDisconnected_Throws()
{
@@ -298,6 +314,7 @@ public class OpcUaClientServiceTests : IDisposable
/// Verifies that writing a string to a node whose current read returns a bad status
/// surfaces a clear error instead of writing a mistyped string value (Client.Shared-008).
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task WriteValueAsync_StringValueWithBadReadStatus_ThrowsInvalidOperationException()
{
@@ -318,6 +335,7 @@ public class OpcUaClientServiceTests : IDisposable
/// Verifies that writing a string to a node whose read returns bad status and null Value
/// surfaces a clear error for both the bad-status case (Client.Shared-008).
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task WriteValueAsync_StringValueWithBadStatus_MessageMentionsNode()
{
@@ -339,6 +357,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that browse results are mapped into the client browse model used by CLI and UI consumers.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task BrowseAsync_WhenConnected_ReturnsMappedResults()
{
@@ -368,6 +387,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that a null browse root defaults to the OPC UA Objects folder.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task BrowseAsync_NullParent_UsesObjectsFolder()
{
@@ -386,6 +406,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that object nodes trigger child-detection checks so the client can mark expandable branches.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task BrowseAsync_ObjectNode_ChecksHasChildren()
{
@@ -414,6 +435,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that browse continuation points are followed so multi-page address-space branches are fully returned.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task BrowseAsync_WithContinuationPoint_FollowsIt()
{
@@ -452,6 +474,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that browse requests are rejected when the client is disconnected.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task BrowseAsync_WhenDisconnected_Throws()
{
@@ -463,6 +486,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that subscribing to a node creates a monitored item on a data-change subscription.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task SubscribeAsync_CreatesSubscription()
{
@@ -479,6 +503,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that duplicate subscribe requests for the same node do not create duplicate monitored items.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task SubscribeAsync_DuplicateNode_IsIdempotent()
{
@@ -495,6 +520,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that data-change notifications from the subscription are raised through the shared client event.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task SubscribeAsync_RaisesDataChangedEvent()
{
@@ -520,6 +546,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that unsubscribing removes the corresponding monitored item from the active subscription.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task UnsubscribeAsync_RemovesMonitoredItem()
{
@@ -537,6 +564,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that unsubscribing an unknown node is treated as a safe no-op.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task UnsubscribeAsync_WhenNotSubscribed_DoesNotThrow()
{
@@ -551,6 +579,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that data subscriptions cannot be created while the client is disconnected.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task SubscribeAsync_WhenDisconnected_Throws()
{
@@ -563,6 +592,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that alarm subscription requests create an event monitored item on the session.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task SubscribeAlarmsAsync_CreatesEventSubscription()
{
@@ -579,6 +609,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that duplicate alarm-subscription requests do not create duplicate event subscriptions.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task SubscribeAlarmsAsync_Duplicate_IsIdempotent()
{
@@ -595,6 +626,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that OPC UA event notifications are mapped into the shared client alarm event model.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task SubscribeAlarmsAsync_RaisesAlarmEvent()
{
@@ -643,6 +675,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that removing alarm monitoring deletes the underlying event subscription.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task UnsubscribeAlarmsAsync_DeletesSubscription()
{
@@ -660,6 +693,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that removing alarms is safe even when no alarm subscription exists.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task UnsubscribeAlarmsAsync_WhenNoSubscription_DoesNotThrow()
{
@@ -673,6 +707,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that condition refresh requests are forwarded to the active alarm subscription.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task RequestConditionRefreshAsync_CallsAdapter()
{
@@ -690,6 +725,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that condition refresh fails fast when no alarm subscription is active.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task RequestConditionRefreshAsync_NoAlarmSubscription_Throws()
{
@@ -704,6 +740,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that alarm subscriptions cannot be created while disconnected.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task SubscribeAlarmsAsync_WhenDisconnected_Throws()
{
@@ -716,6 +753,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that raw history reads return the session-provided values.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task HistoryReadRawAsync_ReturnsValues()
{
@@ -738,6 +776,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that raw history reads are rejected while disconnected.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task HistoryReadRawAsync_WhenDisconnected_Throws()
{
@@ -748,6 +787,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that raw-history failures from the session are propagated to callers.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task HistoryReadRawAsync_SessionThrows_PropagatesException()
{
@@ -762,6 +802,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that aggregate history reads return the processed values from the session adapter.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task HistoryReadAggregateAsync_ReturnsValues()
{
@@ -784,6 +825,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that aggregate history reads are rejected while disconnected.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task HistoryReadAggregateAsync_WhenDisconnected_Throws()
{
@@ -796,6 +838,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that aggregate-history failures from the session are propagated to callers.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task HistoryReadAggregateAsync_SessionThrows_PropagatesException()
{
@@ -814,6 +857,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that redundancy mode, service level, and server URIs are read from the standard OPC UA redundancy nodes.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task GetRedundancyInfoAsync_ReturnsInfo()
{
@@ -846,6 +890,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that missing optional redundancy arrays do not prevent a redundancy snapshot from being returned.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task GetRedundancyInfoAsync_MissingOptionalArrays_ReturnsGracefully()
{
@@ -876,6 +921,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that redundancy inspection is rejected while disconnected.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task GetRedundancyInfoAsync_WhenDisconnected_Throws()
{
@@ -887,6 +933,7 @@ public class OpcUaClientServiceTests : IDisposable
/// Verifies that RedundancySupport boxed as a different numeric type (e.g. short) is handled
/// without InvalidCastException — defensive Convert.ToInt32 coercion (Client.Shared-002).
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task GetRedundancyInfoAsync_RedundancySupportBoxedAsShort_DoesNotThrow()
{
@@ -915,6 +962,7 @@ public class OpcUaClientServiceTests : IDisposable
/// Verifies that a bad-status response for RedundancySupport/ServiceLevel falls back to defaults
/// rather than throwing (Client.Shared-002).
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task GetRedundancyInfoAsync_BadStatusOnRequiredReads_ReturnsDefaults()
{
@@ -944,6 +992,7 @@ public class OpcUaClientServiceTests : IDisposable
/// Verifies that an alarm event with fewer than 6 fields (but at least 1) is still raised
/// with available fields — the old hard &lt;6 early return silently dropped it (Client.Shared-001).
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task OnAlarmEvent_TruncatedFields_StillRaisesEvent()
{
@@ -978,6 +1027,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that a null or empty event field list is silently ignored (defensive guard).
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task OnAlarmEvent_EmptyFields_DoesNotRaiseEvent()
{
@@ -1003,6 +1053,7 @@ public class OpcUaClientServiceTests : IDisposable
/// Verifies that a successful acknowledge call returns <see cref="StatusCodes.Good"/>
/// and reaches the session adapter's CallMethodAsync (Client.Shared-009).
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task AcknowledgeAlarmAsync_OnSuccess_ReturnsGood()
{
@@ -1022,6 +1073,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <see cref="ServiceResultException"/>, so callers using
/// <c>if (StatusCode.IsBad(result))</c> actually see the failure.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task AcknowledgeAlarmAsync_OnServiceResultException_ReturnsBadStatusCode()
{
@@ -1044,6 +1096,7 @@ public class OpcUaClientServiceTests : IDisposable
/// source node, but left alone when the caller already passes the condition node —
/// matches the documented contract.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task AcknowledgeAlarmAsync_LeavesConditionSuffixAlone()
{
@@ -1066,6 +1119,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <c>InAlarm</c>/<c>Acked</c> from the condition node's Galaxy attributes. Verify
/// the alarm event is delivered with the values from the supplemental reads.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task OnAlarmEvent_MissingAckedActiveButHasConditionNode_FallbackReadsAndRaisesEvent()
{
@@ -1139,6 +1193,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that a keep-alive failure moves the client to a configured failover endpoint.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task KeepAliveFailure_TriggersFailover()
{
@@ -1170,6 +1225,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that connection metadata is refreshed to reflect the newly active failover endpoint.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task KeepAliveFailure_UpdatesConnectionInfo()
{
@@ -1196,6 +1252,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that the client falls back to disconnected when every failover endpoint is unreachable.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task KeepAliveFailure_AllEndpointsFail_TransitionsToDisconnected()
{
@@ -1217,6 +1274,7 @@ public class OpcUaClientServiceTests : IDisposable
/// failover loop is still in-flight must be ignored, so only one failover runs and only
/// one replacement session is created.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task KeepAliveFailure_ReentrantWhileFailoverInFlight_RunsFailoverOnce()
{
@@ -1255,6 +1313,7 @@ public class OpcUaClientServiceTests : IDisposable
/// Regression for Client.Shared-005: concurrent subscribe/unsubscribe calls mutating the
/// active-subscription bookkeeping must not corrupt the dictionary or throw.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task SubscribeAndUnsubscribe_ConcurrentCalls_DoNotCorruptState()
{
@@ -1283,6 +1342,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that dispose releases the underlying session and clears exposed connection state.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task Dispose_CleansUpResources()
{
@@ -1299,6 +1359,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that dispose is safe to call even when no connection was established.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public void Dispose_WhenNotConnected_DoesNotThrow()
{
@@ -1308,6 +1369,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that public operations reject use after the shared client has been disposed.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public async Task OperationsAfterDispose_Throw()
{
@@ -1324,6 +1386,7 @@ public class OpcUaClientServiceTests : IDisposable
/// <summary>
/// Verifies that the factory creates a usable shared OPC UA client service instance.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public void OpcUaClientServiceFactory_CreatesService()
{