diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/CliArguments.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/CliArguments.cs
index 5854613..054e1fd 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/CliArguments.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/CliArguments.cs
@@ -44,6 +44,7 @@ internal sealed class CliArguments
/// Returns whether the named flag was present in the arguments.
/// The flag name (without '--' prefix).
+ /// True if the flag was present; otherwise false.
public bool HasFlag(string name)
{
return _flags.Contains(name);
@@ -51,6 +52,7 @@ internal sealed class CliArguments
/// Returns the value for a named argument, or null if absent.
/// The argument name (without '--' prefix).
+ /// The argument value, or null if the argument was not provided.
public string? GetOptional(string name)
{
return _values.TryGetValue(name, out string? value)
@@ -60,6 +62,7 @@ internal sealed class CliArguments
/// Returns the value for a required named argument, or throws if absent.
/// The argument name (without '--' prefix).
+ /// The argument value.
public string GetRequired(string name)
{
string? value = GetOptional(name);
@@ -74,6 +77,7 @@ internal sealed class CliArguments
/// Parses and returns an int32 argument, or the default value if absent.
/// The argument name (without '--' prefix).
/// The default value if the argument is absent; if null, the argument is required.
+ /// The parsed int32 value, or the default if absent.
public int GetInt32(string name, int? defaultValue = null)
{
string? value = GetOptional(name);
@@ -93,6 +97,7 @@ internal sealed class CliArguments
/// Parses and returns a uint32 argument, or the default value if absent.
/// The argument name (without '--' prefix).
/// The default value if the argument is absent.
+ /// The parsed uint32 value, or the default if absent.
public uint GetUInt32(string name, uint defaultValue)
{
string? value = GetOptional(name);
@@ -104,6 +109,7 @@ internal sealed class CliArguments
/// Parses and returns a uint64 argument, or the default value if absent.
/// The argument name (without '--' prefix).
/// The default value if the argument is absent.
+ /// The parsed uint64 value, or the default if absent.
public ulong GetUInt64(string name, ulong defaultValue)
{
string? value = GetOptional(name);
@@ -115,6 +121,7 @@ internal sealed class CliArguments
/// Parses and returns a TimeSpan argument, or the default value if absent. Supports "ms", "s", and standard TimeSpan format.
/// The argument name (without '--' prefix).
/// The default value if the argument is absent.
+ /// The parsed TimeSpan value, or the default if absent.
public TimeSpan GetDuration(string name, TimeSpan defaultValue)
{
string? value = GetOptional(name);
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/MxGatewayCliClientAdapter.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/MxGatewayCliClientAdapter.cs
index 6601dcb..9a30c8c 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/MxGatewayCliClientAdapter.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/MxGatewayCliClientAdapter.cs
@@ -100,7 +100,8 @@ internal sealed class MxGatewayCliClientAdapter : IMxGatewayCliClient
return _galaxyClient.Value.WatchDeployEventsRawAsync(request, cancellationToken);
}
- ///
+ /// Disposes the galaxy client (if created) and the underlying gateway client.
+ /// A value task that completes when both clients are disposed.
public async ValueTask DisposeAsync()
{
if (_galaxyClient.IsValueCreated)
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/MxGatewayCliSecretRedactor.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/MxGatewayCliSecretRedactor.cs
index d4e3003..1a2a563 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/MxGatewayCliSecretRedactor.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/MxGatewayCliSecretRedactor.cs
@@ -6,6 +6,7 @@ internal static class MxGatewayCliSecretRedactor
/// Replaces occurrences of the API key in the value with a redacted placeholder.
/// The message text to redact.
/// The API key to remove; no redaction if null or empty.
+ /// The message text with any API key occurrence replaced by [redacted].
public static string Redact(string value, string? apiKey)
{
if (string.IsNullOrEmpty(value) || string.IsNullOrEmpty(apiKey))
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/MxGatewayClientCli.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/MxGatewayClientCli.cs
index 8f2ff53..184da00 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/MxGatewayClientCli.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli/MxGatewayClientCli.cs
@@ -22,6 +22,7 @@ public static class MxGatewayClientCli
/// Command-line arguments (command name followed by options).
/// TextWriter for command output.
/// TextWriter for error messages.
+ /// The process exit code (0 for success, 1 for error).
public static int Run(
string[] args,
TextWriter standardOutput,
@@ -38,6 +39,7 @@ public static class MxGatewayClientCli
/// TextWriter for error messages.
/// Optional factory to create the gateway client; defaults to MxGatewayClient.Create.
/// Optional TextReader for batch-mode stdin; defaults to .
+ /// A task that resolves to the process exit code (0 for success, 1 for error).
public static Task RunAsync(
string[] args,
TextWriter standardOutput,
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/BrowseChildrenSmokeTests.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/BrowseChildrenSmokeTests.cs
index dd5f48e..943a106 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/BrowseChildrenSmokeTests.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/BrowseChildrenSmokeTests.cs
@@ -14,6 +14,7 @@ public sealed class BrowseChildrenSmokeTests
/// Verifies that BrowseChildren returns a non-zero cache sequence and
/// a consistent children/child-has-children count from a live gateway.
///
+ /// A task that represents the asynchronous operation.
[Fact(Skip = "Set MXGATEWAY_API_KEY and MXGATEWAY_ENDPOINT to enable.")]
public async Task BrowseChildren_LiveGateway_ReturnsRootsWithCacheSequence()
{
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/FakeGalaxyRepositoryTransport.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/FakeGalaxyRepositoryTransport.cs
index 1ec00d1..e07d6de 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/FakeGalaxyRepositoryTransport.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/FakeGalaxyRepositoryTransport.cs
@@ -8,14 +8,10 @@ namespace ZB.MOM.WW.MxGateway.Client.Tests;
///
internal sealed class FakeGalaxyRepositoryTransport(MxGatewayClientOptions options) : IGalaxyRepositoryClientTransport
{
- ///
- /// Gets the gateway client options.
- ///
+ ///
public MxGatewayClientOptions Options { get; } = options;
- ///
- /// Gets the raw gRPC client; always null for the fake.
- ///
+ ///
public GalaxyRepository.GalaxyRepositoryClient? RawClient => null;
///
@@ -66,11 +62,7 @@ internal sealed class FakeGalaxyRepositoryTransport(MxGatewayClientOptions optio
///
public Queue DiscoverHierarchyExceptions { get; } = new();
- ///
- /// Records the request and either throws a queued exception or returns the configured reply.
- ///
- /// The TestConnectionRequest to process.
- /// Call options specifying RPC behavior.
+ ///
public Task TestConnectionAsync(
TestConnectionRequest request,
CallOptions callOptions)
@@ -84,11 +76,7 @@ internal sealed class FakeGalaxyRepositoryTransport(MxGatewayClientOptions optio
return Task.FromResult(TestConnectionReply);
}
- ///
- /// Records the request and either throws a queued exception or returns the configured reply.
- ///
- /// The GetLastDeployTimeRequest to process.
- /// Call options specifying RPC behavior.
+ ///
public Task GetLastDeployTimeAsync(
GetLastDeployTimeRequest request,
CallOptions callOptions)
@@ -102,11 +90,7 @@ internal sealed class FakeGalaxyRepositoryTransport(MxGatewayClientOptions optio
return Task.FromResult(GetLastDeployTimeReply);
}
- ///
- /// Records the request and either throws a queued exception or returns the configured reply.
- ///
- /// The DiscoverHierarchyRequest to process.
- /// Call options specifying RPC behavior.
+ ///
public Task DiscoverHierarchyAsync(
DiscoverHierarchyRequest request,
CallOptions callOptions)
@@ -135,11 +119,7 @@ internal sealed class FakeGalaxyRepositoryTransport(MxGatewayClientOptions optio
/// Queue of exceptions to throw from BrowseChildren; dequeued in FIFO order.
public Queue BrowseChildrenExceptions { get; } = new();
- ///
- /// Records the request and either throws a queued exception or returns the configured reply.
- ///
- /// The BrowseChildrenRequest to process.
- /// Call options specifying RPC behavior.
+ ///
public Task BrowseChildrenAsync(
BrowseChildrenRequest request,
CallOptions callOptions)
@@ -177,11 +157,7 @@ internal sealed class FakeGalaxyRepositoryTransport(MxGatewayClientOptions optio
///
public Func? WatchDeployEventsBeforeYield { get; set; }
- ///
- /// Records the request and streams events, checking for queued exceptions and calling WatchDeployEventsBeforeYield before each event.
- ///
- /// The WatchDeployEventsRequest to process.
- /// Call options specifying RPC behavior.
+ ///
public async IAsyncEnumerable WatchDeployEventsAsync(
WatchDeployEventsRequest request,
CallOptions callOptions)
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/FakeGatewayTransport.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/FakeGatewayTransport.cs
index 7e81274..cb677fc 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/FakeGatewayTransport.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/FakeGatewayTransport.cs
@@ -11,14 +11,10 @@ internal sealed class FakeGatewayTransport(MxGatewayClientOptions options) : IMx
private readonly Queue _invokeReplies = new();
private readonly List _events = [];
- ///
- /// Gets the gateway client options.
- ///
+ ///
public MxGatewayClientOptions Options { get; } = options;
- ///
- /// Gets null, since this is a test fake without a real gRPC client.
- ///
+ ///
public MxAccessGateway.MxAccessGatewayClient? RawClient => null;
///
@@ -102,11 +98,7 @@ internal sealed class FakeGatewayTransport(MxGatewayClientOptions options) : IMx
///
public Queue InvokeExceptions { get; } = new();
- ///
- /// Verifies that the OpenSessionAsync call is recorded and returns the configured reply.
- ///
- /// The OpenSessionRequest to process.
- /// Call options specifying RPC behavior.
+ ///
public Task OpenSessionAsync(
OpenSessionRequest request,
CallOptions callOptions)
@@ -120,11 +112,7 @@ internal sealed class FakeGatewayTransport(MxGatewayClientOptions options) : IMx
return Task.FromResult(OpenSessionReply);
}
- ///
- /// Verifies that the CloseSessionAsync call is recorded and returns the configured reply.
- ///
- /// The CloseSessionRequest to process.
- /// Call options specifying RPC behavior.
+ ///
public Task CloseSessionAsync(
CloseSessionRequest request,
CallOptions callOptions)
@@ -138,11 +126,7 @@ internal sealed class FakeGatewayTransport(MxGatewayClientOptions options) : IMx
return Task.FromResult(CloseSessionReply);
}
- ///
- /// Verifies that the InvokeAsync call is recorded and returns the next enqueued reply.
- ///
- /// The MxCommandRequest to process.
- /// Call options specifying RPC behavior.
+ ///
public Task InvokeAsync(
MxCommandRequest request,
CallOptions callOptions)
@@ -156,11 +140,7 @@ internal sealed class FakeGatewayTransport(MxGatewayClientOptions options) : IMx
return Task.FromResult(_invokeReplies.Dequeue());
}
- ///
- /// Verifies that the StreamEventsAsync call is recorded and yields all enqueued events.
- ///
- /// The StreamEventsRequest to process.
- /// Call options specifying RPC behavior.
+ ///
public async IAsyncEnumerable StreamEventsAsync(
StreamEventsRequest request,
CallOptions callOptions)
@@ -193,11 +173,7 @@ internal sealed class FakeGatewayTransport(MxGatewayClientOptions options) : IMx
_events.Add(gatewayEvent);
}
- ///
- /// Records the acknowledge call and returns the next enqueued reply (or default).
- ///
- /// The acknowledge alarm request.
- /// Call options specifying RPC behavior.
+ ///
public Task AcknowledgeAlarmAsync(
AcknowledgeAlarmRequest request,
CallOptions callOptions)
@@ -218,11 +194,7 @@ internal sealed class FakeGatewayTransport(MxGatewayClientOptions options) : IMx
});
}
- ///
- /// Records the query call and yields each enqueued snapshot.
- ///
- /// The query active alarms request.
- /// Call options specifying RPC behavior.
+ ///
public async IAsyncEnumerable QueryActiveAlarmsAsync(
QueryActiveAlarmsRequest request,
CallOptions callOptions)
@@ -251,11 +223,7 @@ internal sealed class FakeGatewayTransport(MxGatewayClientOptions options) : IMx
_activeAlarmSnapshots.Add(snapshot);
}
- ///
- /// Records the stream-alarms call and yields each enqueued feed message.
- ///
- /// The stream alarms request.
- /// Call options specifying RPC behavior.
+ ///
public async IAsyncEnumerable StreamAlarmsAsync(
StreamAlarmsRequest request,
CallOptions callOptions)
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/GalaxyRepositoryClientTests.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/GalaxyRepositoryClientTests.cs
index 351a9d2..184bde7 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/GalaxyRepositoryClientTests.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/GalaxyRepositoryClientTests.cs
@@ -9,6 +9,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that TestConnectionAsync attaches the API key in request metadata and returns the Ok flag.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task TestConnectionAsync_AttachesApiKeyMetadataAndReturnsOkFlag()
{
@@ -27,6 +28,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that TestConnectionAsync returns false when the server reports NotOk.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task TestConnectionAsync_ReturnsFalseWhenServerReportsNotOk()
{
@@ -42,6 +44,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that GetLastDeployTimeAsync returns null when the server reports not present.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task GetLastDeployTimeAsync_ReturnsNullWhenNotPresent()
{
@@ -58,6 +61,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that GetLastDeployTimeAsync returns the timestamp when the server reports it present.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task GetLastDeployTimeAsync_ReturnsTimestampWhenPresent()
{
@@ -79,6 +83,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that DiscoverHierarchyAsync returns the objects from the server reply.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DiscoverHierarchyAsync_ReturnsObjectsFromReply()
{
@@ -141,6 +146,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that DiscoverHierarchyAsync propagates cancellation tokens to the transport.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DiscoverHierarchyAsync_PropagatesCancellationToTransport()
{
@@ -161,6 +167,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that TestConnectionAsync retries on transient gRPC failures.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DiscoverHierarchyAsync_WithRepeatedPageToken_ThrowsProtocolError()
{
@@ -184,6 +191,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that DiscoverHierarchyAsync maps typed filter options correctly to the request.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DiscoverHierarchyAsync_WithOptions_MapsTypedFilters()
{
@@ -218,6 +226,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that TestConnectionAsync retries on transient gRPC failures.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task TestConnectionAsync_RetriesOnTransientGrpcFailure()
{
@@ -235,6 +244,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that DiscoverHierarchyAsync retries on transient gRPC failures.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DiscoverHierarchyAsync_RetriesOnTransientGrpcFailure()
{
@@ -251,6 +261,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that WatchDeployEventsAsync delivers the bootstrap event.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WatchDeployEventsAsync_DeliversBootstrapEvent()
{
@@ -287,6 +298,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that WatchDeployEventsAsync delivers multiple events in order.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WatchDeployEventsAsync_DeliversMultipleEventsInOrder()
{
@@ -325,6 +337,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that WatchDeployEventsAsync stops iteration cleanly when cancelled.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WatchDeployEventsAsync_CancellationStopsIterationCleanly()
{
@@ -369,6 +382,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that WatchDeployEventsAsync throws ObjectDisposedException after the client is disposed.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WatchDeployEventsAsync_ThrowsAfterDisposal()
{
@@ -384,6 +398,7 @@ public sealed class GalaxyRepositoryClientTests
///
/// Verifies that TestConnectionAsync throws ObjectDisposedException after the client is disposed.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task TestConnectionAsync_ThrowsAfterDisposal()
{
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/LazyBrowseNodeTests.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/LazyBrowseNodeTests.cs
index b4d5452..79e1781 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/LazyBrowseNodeTests.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/LazyBrowseNodeTests.cs
@@ -12,6 +12,7 @@ public sealed class LazyBrowseNodeTests
/// Verifies that calling BrowseAsync with no parent returns the root nodes
/// from the first BrowseChildren reply and surfaces the per-child has-children hint.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Browse_NoParent_ReturnsRoots()
{
@@ -36,6 +37,7 @@ public sealed class LazyBrowseNodeTests
///
/// Verifies that ExpandAsync populates Children and marks the node expanded after one RPC.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Expand_PopulatesChildrenAndMarksExpanded()
{
@@ -62,6 +64,7 @@ public sealed class LazyBrowseNodeTests
///
/// Verifies that a second ExpandAsync call is a no-op and issues no additional RPC.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Expand_CalledTwice_NoSecondRpc()
{
@@ -86,6 +89,7 @@ public sealed class LazyBrowseNodeTests
///
/// Verifies that an RPC failure (NotFound) during expand is wrapped in MxGatewayException.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Expand_UnknownParent_ThrowsMxGatewayException()
{
@@ -113,6 +117,7 @@ public sealed class LazyBrowseNodeTests
///
/// Verifies that ExpandAsync drains multi-page sibling replies and forwards the page token.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Expand_MultiPageSiblings_GathersAllPages()
{
@@ -147,6 +152,7 @@ public sealed class LazyBrowseNodeTests
///
/// Verifies that ten concurrent ExpandAsync calls issue exactly one RPC, not ten.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Expand_CalledConcurrently_OnlyFiresOneRpc()
{
@@ -178,6 +184,7 @@ public sealed class LazyBrowseNodeTests
///
/// Verifies that BrowseChildrenOptions filter fields are forwarded to the BrowseChildren request.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Browse_WithFilter_ForwardsToRequest()
{
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayClientAlarmsTests.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayClientAlarmsTests.cs
index b178944..61582b6 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayClientAlarmsTests.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayClientAlarmsTests.cs
@@ -12,6 +12,7 @@ namespace ZB.MOM.WW.MxGateway.Client.Tests;
public sealed class MxGatewayClientAlarmsTests
{
/// AcknowledgeAlarmAsync records request and returns reply.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AcknowledgeAlarmAsync_RecordsRequestShapeAndReturnsReply()
{
@@ -48,6 +49,7 @@ public sealed class MxGatewayClientAlarmsTests
}
/// AcknowledgeAlarmAsync honors cancellation.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AcknowledgeAlarmAsync_HonorsCancellation()
{
@@ -72,6 +74,7 @@ public sealed class MxGatewayClientAlarmsTests
}
/// AcknowledgeAlarmAsync maps unauthenticated RPC exception to typed exception.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AcknowledgeAlarmAsync_MapsUnauthenticated_RpcException_ToTypedException()
{
@@ -97,6 +100,7 @@ public sealed class MxGatewayClientAlarmsTests
}
/// QueryActiveAlarmsAsync streams enqueued snapshots.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task QueryActiveAlarmsAsync_StreamsEnqueuedSnapshots()
{
@@ -122,6 +126,7 @@ public sealed class MxGatewayClientAlarmsTests
}
/// QueryActiveAlarmsAsync passes filter prefix.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task QueryActiveAlarmsAsync_PassesFilterPrefix()
{
@@ -142,6 +147,7 @@ public sealed class MxGatewayClientAlarmsTests
}
/// QueryActiveAlarmsAsync honors cancellation during enumeration.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task QueryActiveAlarmsAsync_HonorsCancellationDuringEnumeration()
{
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayClientCliTests.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayClientCliTests.cs
index a63ec30..6018771 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayClientCliTests.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayClientCliTests.cs
@@ -24,6 +24,7 @@ public sealed class MxGatewayClientCliTests
}
/// Verifies that the version command with --json flag prints JSON protocol versions.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_VersionJson_PrintsJsonProtocolVersions()
{
@@ -38,6 +39,7 @@ public sealed class MxGatewayClientCliTests
}
/// Verifies that the write command builds a write request and prints JSON reply.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_Write_BuildsWriteCommandAndPrintsJsonReply()
{
@@ -83,6 +85,7 @@ public sealed class MxGatewayClientCliTests
}
/// Verifies that error output redacts sensitive API key values.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_ErrorOutput_RedactsApiKey()
{
@@ -107,6 +110,7 @@ public sealed class MxGatewayClientCliTests
}
/// Verifies that stream-events with max-events limit stops output in non-JSON format.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_StreamEvents_WithMaxEventsStopsNonJsonOutput()
{
@@ -149,6 +153,7 @@ public sealed class MxGatewayClientCliTests
/// Verifies that stream-alarms with --max-events stops output and distinguishes payload cases.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_StreamAlarms_WithMaxEventsStopsAndDistinguishesPayloadCases()
{
@@ -188,6 +193,7 @@ public sealed class MxGatewayClientCliTests
}
/// Verifies that acknowledge-alarm builds a request and prints the JSON reply.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_AcknowledgeAlarm_BuildsRequestAndPrintsJsonReply()
{
@@ -230,6 +236,7 @@ public sealed class MxGatewayClientCliTests
}
/// Verifies that smoke command closes opened session when a command fails.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_Smoke_WhenCommandFails_ClosesOpenedSession()
{
@@ -261,6 +268,7 @@ public sealed class MxGatewayClientCliTests
}
/// Verifies that galaxy-test-connection command prints JSON reply.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_GalaxyTestConnection_PrintsJsonReply()
{
@@ -291,6 +299,7 @@ public sealed class MxGatewayClientCliTests
}
/// Verifies that galaxy-discover command prints hierarchy summary.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_GalaxyDiscover_PrintsHierarchySummary()
{
@@ -361,6 +370,7 @@ public sealed class MxGatewayClientCliTests
}
/// Verifies that galaxy-watch command prints text output for deploy events.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_GalaxyWatch_PrintsTextOutputForEvents()
{
@@ -415,6 +425,7 @@ public sealed class MxGatewayClientCliTests
}
/// Verifies that galaxy-watch with --json emits one JSON object per event.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_GalaxyWatch_JsonEmitsOneObjectPerEvent()
{
@@ -450,6 +461,7 @@ public sealed class MxGatewayClientCliTests
}
/// Verifies that batch mode dispatches a single version command and emits the EOR sentinel.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_Batch_DispatchesVersionAndWritesEndOfRecord()
{
@@ -476,6 +488,7 @@ public sealed class MxGatewayClientCliTests
}
/// Verifies that batch mode routes per-command errors to stdout as JSON between EOR markers.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_Batch_WritesErrorsToStdoutAsJson()
{
@@ -520,6 +533,7 @@ public sealed class MxGatewayClientCliTests
/// against exit code 0.
///
/// The alarm subcommand to validate (e.g. "stream-alarms", "acknowledge-alarm").
+ /// A task that represents the asynchronous operation.
[Theory]
[InlineData("stream-alarms")]
[InlineData("acknowledge-alarm")]
@@ -574,6 +588,7 @@ public sealed class MxGatewayClientCliTests
/// against a zero server handle. The fix must fail loudly with a
/// descriptive .
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_BenchReadBulk_WhenRegisterReplyMissingTypedPayload_FailsLoudly()
{
@@ -624,6 +639,7 @@ public sealed class MxGatewayClientCliTests
/// kept spinning until --duration-seconds elapsed. After the fix
/// the bench must exit promptly when the supplied token cancels.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_BenchReadBulk_WhenSteadyStateLoopReceivesCancellation_ExitsPromptly()
{
@@ -718,6 +734,7 @@ public sealed class MxGatewayClientCliTests
/// to ~49.7 days. The fix must reject negatives with a clear error.
///
/// The bulk-read subcommand to validate (e.g. "read-bulk", "bench-read-bulk").
+ /// A task that represents the asynchronous operation.
[Theory]
[InlineData("read-bulk")]
[InlineData("bench-read-bulk")]
@@ -880,7 +897,8 @@ public sealed class MxGatewayClientCliTests
/// Optional per-call handler that overrides queue-based behaviour.
public Func>? InvokeHandler { get; init; }
- ///
+ /// Releases resources held by the fake CLI client.
+ /// A completed value task.
public ValueTask DisposeAsync()
{
return ValueTask.CompletedTask;
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayClientSessionTests.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayClientSessionTests.cs
index 1052a8d..66bc654 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayClientSessionTests.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayClientSessionTests.cs
@@ -7,6 +7,7 @@ namespace ZB.MOM.WW.MxGateway.Client.Tests;
public sealed class MxGatewayClientSessionTests
{
/// Verifies that open session attaches API key metadata and cancellation token.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task OpenSessionRawAsync_AttachesApiKeyMetadataAndCancellation()
{
@@ -22,6 +23,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that open session returns a session with the raw open reply.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task OpenSessionAsync_ReturnsSessionWithRawOpenReply()
{
@@ -37,6 +39,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that register builds a register command and returns server handle.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RegisterAsync_BuildsRegisterCommandAndReturnsServerHandle()
{
@@ -62,6 +65,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that add item 2 builds a command with the specified context.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AddItem2Async_BuildsAddItem2CommandWithContext()
{
@@ -87,6 +91,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that write raw builds a write command with the raw value.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WriteRawAsync_BuildsWriteCommandWithRawValue()
{
@@ -118,6 +123,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that write 2 raw builds a write 2 command with value and timestamp.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Write2RawAsync_BuildsWrite2CommandWithValueAndTimestamp()
{
@@ -146,6 +152,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that subscribe bulk builds one command and returns per-item results.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SubscribeBulkAsync_BuildsOneBulkCommandAndReturnsPerItemResults()
{
@@ -185,6 +192,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that stream events yields events in the order received from the gateway.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task StreamEventsAsync_YieldsEventsInGatewayOrder()
{
@@ -216,6 +224,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that close is explicit and idempotent.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CloseAsync_IsExplicitAndIdempotent()
{
@@ -232,6 +241,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that invoke retries safe diagnostic commands on transient RPC failure.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InvokeAsync_RetriesSafeDiagnosticCommandOnTransientGrpcFailure()
{
@@ -256,6 +266,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that open session does not retry on transient RPC failure.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task OpenSessionAsync_DoesNotRetryTransientGrpcFailure()
{
@@ -269,6 +280,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that invoke does not retry write commands on transient RPC failure.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InvokeAsync_DoesNotRetryWriteCommand()
{
@@ -284,6 +296,7 @@ public sealed class MxGatewayClientSessionTests
}
/// Verifies that invoke helpers pass cancellation token to the transport.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InvokeHelpers_PassCancellationTokenToTransport()
{
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayGeneratedContractTests.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayGeneratedContractTests.cs
index 95fdd89..7c1593a 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayGeneratedContractTests.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client.Tests/MxGatewayGeneratedContractTests.cs
@@ -3,6 +3,7 @@ namespace ZB.MOM.WW.MxGateway.Client.Tests;
public sealed class MxGatewayGeneratedContractTests
{
/// Verifies that the generated gRPC client can be instantiated from the client factory.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task GeneratedGrpcClient_CanBeConstructedFromClientFactory()
{
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/GalaxyRepositoryClient.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/GalaxyRepositoryClient.cs
index 7d05638..0e7ceaa 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/GalaxyRepositoryClient.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/GalaxyRepositoryClient.cs
@@ -337,6 +337,9 @@ public sealed class GalaxyRepositoryClient : IAsyncDisposable
cancellationToken);
}
+ /// Builds a from the provided options.
+ /// Browse children options to convert.
+ /// The constructed request message.
internal static BrowseChildrenRequest BuildBrowseChildrenRequest(BrowseChildrenOptions options)
{
ArgumentNullException.ThrowIfNull(options);
@@ -424,6 +427,7 @@ public sealed class GalaxyRepositoryClient : IAsyncDisposable
///
/// Closes the gRPC channel and releases resources.
///
+ /// A task that represents the asynchronous dispose operation.
public ValueTask DisposeAsync()
{
if (_disposed)
@@ -493,6 +497,9 @@ public sealed class GalaxyRepositoryClient : IAsyncDisposable
private static HttpMessageHandler CreateHttpHandler(MxGatewayClientOptions options) =>
CreateHttpHandlerForTests(options);
+ /// Creates an configured from the provided options for test use.
+ /// Client options used to configure TLS and timeouts.
+ /// The configured HTTP message handler.
internal static SocketsHttpHandler CreateHttpHandlerForTests(MxGatewayClientOptions options)
{
SocketsHttpHandler handler = new()
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/GrpcGalaxyRepositoryClientTransport.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/GrpcGalaxyRepositoryClientTransport.cs
index e51337e..1d8e4a2 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/GrpcGalaxyRepositoryClientTransport.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/GrpcGalaxyRepositoryClientTransport.cs
@@ -10,9 +10,7 @@ internal sealed class GrpcGalaxyRepositoryClientTransport(
MxGatewayClientOptions options,
GalaxyRepository.GalaxyRepositoryClient rawClient) : IGalaxyRepositoryClientTransport
{
- ///
- /// Gets the gateway client options.
- ///
+ ///
public MxGatewayClientOptions Options { get; } = options;
///
@@ -91,7 +89,11 @@ internal sealed class GrpcGalaxyRepositoryClientTransport(
}
}
- ///
+ /// Streams deploy events from the Galaxy Repository, using an explicit cancellation token that overrides the call options token when provided.
+ /// The watch deploy events request.
+ /// Call options for the underlying gRPC call.
+ /// Optional cancellation token; takes precedence over the token in when cancellable.
+ /// An async enumerable of deploy events.
public async IAsyncEnumerable WatchDeployEventsAsync(
WatchDeployEventsRequest request,
CallOptions callOptions,
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/GrpcMxGatewayClientTransport.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/GrpcMxGatewayClientTransport.cs
index 5ff4e75..eac5b26 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/GrpcMxGatewayClientTransport.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/GrpcMxGatewayClientTransport.cs
@@ -10,9 +10,7 @@ internal sealed class GrpcMxGatewayClientTransport(
MxGatewayClientOptions options,
MxAccessGateway.MxAccessGatewayClient rawClient) : IMxGatewayClientTransport
{
- ///
- /// Gets the gateway client options.
- ///
+ ///
public MxGatewayClientOptions Options { get; } = options;
///
@@ -74,7 +72,11 @@ internal sealed class GrpcMxGatewayClientTransport(
}
}
- ///
+ /// Streams MXAccess events from the gateway, forwarding an explicit cancellation token to the stream reader.
+ /// The stream events request.
+ /// gRPC call options.
+ /// Token to cancel the streaming enumeration.
+ /// An async enumerable of MXAccess events.
public async IAsyncEnumerable StreamEventsAsync(
StreamEventsRequest request,
CallOptions callOptions,
@@ -133,7 +135,11 @@ internal sealed class GrpcMxGatewayClientTransport(
}
}
- ///
+ /// Queries active alarms from the gateway, forwarding an explicit cancellation token to the stream reader.
+ /// The query active alarms request.
+ /// gRPC call options.
+ /// Token to cancel the streaming enumeration.
+ /// An async enumerable of active alarm snapshots.
public async IAsyncEnumerable QueryActiveAlarmsAsync(
QueryActiveAlarmsRequest request,
CallOptions callOptions,
@@ -175,7 +181,11 @@ internal sealed class GrpcMxGatewayClientTransport(
return QueryActiveAlarmsAsync(request, callOptions);
}
- ///
+ /// Streams alarm feed messages from the gateway, forwarding an explicit cancellation token to the stream reader.
+ /// The stream alarms request.
+ /// gRPC call options.
+ /// Token to cancel the streaming enumeration.
+ /// An async enumerable of alarm feed messages.
public async IAsyncEnumerable StreamAlarmsAsync(
StreamAlarmsRequest request,
CallOptions callOptions,
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/IGalaxyRepositoryClientTransport.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/IGalaxyRepositoryClientTransport.cs
index ddc5dcc..e9348c3 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/IGalaxyRepositoryClientTransport.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/IGalaxyRepositoryClientTransport.cs
@@ -15,6 +15,7 @@ internal interface IGalaxyRepositoryClientTransport
/// Tests the connection to the Galaxy Repository server.
/// The test connection request.
/// gRPC call options (timeout, cancellation, etc.).
+ /// A task that resolves to the test connection reply.
Task TestConnectionAsync(
TestConnectionRequest request,
CallOptions callOptions);
@@ -22,6 +23,7 @@ internal interface IGalaxyRepositoryClientTransport
/// Gets the last deploy time from the Galaxy Repository server.
/// The get last deploy time request.
/// gRPC call options (timeout, cancellation, etc.).
+ /// A task that resolves to the last deploy time reply.
Task GetLastDeployTimeAsync(
GetLastDeployTimeRequest request,
CallOptions callOptions);
@@ -29,6 +31,7 @@ internal interface IGalaxyRepositoryClientTransport
/// Discovers the object hierarchy in the Galaxy Repository.
/// The discover hierarchy request.
/// gRPC call options (timeout, cancellation, etc.).
+ /// A task that resolves to the hierarchy discovery reply.
Task DiscoverHierarchyAsync(
DiscoverHierarchyRequest request,
CallOptions callOptions);
@@ -36,6 +39,7 @@ internal interface IGalaxyRepositoryClientTransport
/// Returns direct children of a parent in the Galaxy hierarchy.
/// The browse children request.
/// gRPC call options (timeout, cancellation, etc.).
+ /// A task that resolves to the browse children reply.
Task BrowseChildrenAsync(
BrowseChildrenRequest request,
CallOptions callOptions);
@@ -43,6 +47,7 @@ internal interface IGalaxyRepositoryClientTransport
/// Watches for deployment events from the Galaxy Repository server.
/// The watch deploy events request.
/// gRPC call options (timeout, cancellation, etc.).
+ /// An async enumerable of deploy events.
IAsyncEnumerable WatchDeployEventsAsync(
WatchDeployEventsRequest request,
CallOptions callOptions);
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/LazyBrowseNode.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/LazyBrowseNode.cs
index 360f4f5..b13cdcf 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/LazyBrowseNode.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/LazyBrowseNode.cs
@@ -16,6 +16,11 @@ public sealed class LazyBrowseNode
private readonly SemaphoreSlim _expandLock = new(1, 1);
private bool _isExpanded;
+ /// Initializes a new instance of .
+ /// The repository client used to fetch children.
+ /// The underlying Galaxy object for this node.
+ /// True when the server reports the node has at least one matching descendant.
+ /// Options controlling child browse behavior.
internal LazyBrowseNode(
GalaxyRepositoryClient client,
GalaxyObject @object,
@@ -49,6 +54,7 @@ public sealed class LazyBrowseNode
/// (after the first completes) return immediately.
///
/// Token to observe for cancellation.
+ /// A task that represents the asynchronous operation.
public async Task ExpandAsync(CancellationToken cancellationToken = default)
{
if (_isExpanded)
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxCommandReplyExtensions.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxCommandReplyExtensions.cs
index ef111df..7546d7d 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxCommandReplyExtensions.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxCommandReplyExtensions.cs
@@ -7,6 +7,7 @@ public static class MxCommandReplyExtensions
{
/// Validates that the reply has a successful protocol status (Ok or MxAccessFailure), throwing a gateway exception if not.
/// The command reply to check.
+ /// The same for fluent chaining when validation passes.
public static MxCommandReply EnsureProtocolSuccess(this MxCommandReply reply)
{
ArgumentNullException.ThrowIfNull(reply);
@@ -24,6 +25,7 @@ public static class MxCommandReplyExtensions
/// Validates that the reply indicates MXAccess success (no HResult or status failures), throwing MxAccessException if not.
/// The command reply to check.
+ /// The same for fluent chaining when validation passes.
public static MxCommandReply EnsureMxAccessSuccess(this MxCommandReply reply)
{
ArgumentNullException.ThrowIfNull(reply);
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxGatewayClient.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxGatewayClient.cs
index 6d9ab58..a70ff5b 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxGatewayClient.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxGatewayClient.cs
@@ -249,6 +249,7 @@ public sealed class MxGatewayClient : IAsyncDisposable
///
/// Disposes the client and releases all resources.
///
+ /// A task that represents the asynchronous dispose operation.
public ValueTask DisposeAsync()
{
if (_disposed)
@@ -318,6 +319,9 @@ public sealed class MxGatewayClient : IAsyncDisposable
private static HttpMessageHandler CreateHttpHandler(MxGatewayClientOptions options) =>
CreateHttpHandlerForTests(options);
+ /// Creates an configured from the provided options for test use.
+ /// Client options used to configure TLS and timeouts.
+ /// The configured HTTP message handler.
internal static SocketsHttpHandler CreateHttpHandlerForTests(MxGatewayClientOptions options)
{
SocketsHttpHandler handler = new()
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxGatewayClientRetryPolicy.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxGatewayClientRetryPolicy.cs
index ff4ff7a..757df75 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxGatewayClientRetryPolicy.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxGatewayClientRetryPolicy.cs
@@ -12,6 +12,7 @@ internal static class MxGatewayClientRetryPolicy
/// Creates a Polly ResiliencePipeline that retries transient gRPC failures with exponential backoff.
/// Retry configuration (max attempts, delay bounds, jitter).
/// Optional logger for retry diagnostics.
+ /// A configured with exponential-backoff retry.
public static ResiliencePipeline Create(
MxGatewayClientRetryOptions options,
ILogger? logger)
@@ -42,6 +43,7 @@ internal static class MxGatewayClientRetryPolicy
/// Returns whether a command kind is eligible for automatic retry on transient failures.
/// The command kind to check.
+ /// if the command kind is safe to retry; otherwise .
public static bool IsRetryableCommand(MxCommandKind kind)
{
return kind is MxCommandKind.Ping
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxGatewaySession.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxGatewaySession.cs
index 158589c..2caf220 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxGatewaySession.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxGatewaySession.cs
@@ -211,6 +211,7 @@ public sealed class MxGatewaySession : IAsyncDisposable
/// The ServerHandle from register.
/// The ItemHandle from add-item.
/// Cancellation token.
+ /// A task that represents the asynchronous operation.
public async Task AdviseAsync(
int serverHandle,
int itemHandle,
@@ -252,6 +253,7 @@ public sealed class MxGatewaySession : IAsyncDisposable
/// The ServerHandle from register.
/// The ItemHandle from add-item.
/// Cancellation token.
+ /// A task that represents the asynchronous operation.
public async Task UnAdviseAsync(
int serverHandle,
int itemHandle,
@@ -293,6 +295,7 @@ public sealed class MxGatewaySession : IAsyncDisposable
/// The ServerHandle from register.
/// The ItemHandle from add-item.
/// Cancellation token.
+ /// A task that represents the asynchronous operation.
public async Task RemoveItemAsync(
int serverHandle,
int itemHandle,
@@ -675,6 +678,7 @@ public sealed class MxGatewaySession : IAsyncDisposable
/// The value to write.
/// User ID context for the write.
/// Cancellation token.
+ /// A task that represents the asynchronous operation.
public async Task WriteAsync(
int serverHandle,
int itemHandle,
@@ -729,6 +733,7 @@ public sealed class MxGatewaySession : IAsyncDisposable
/// The timestamp to write with the value.
/// User ID context for the write.
/// Cancellation token.
+ /// A task that represents the asynchronous operation.
public async Task Write2Async(
int serverHandle,
int itemHandle,
@@ -821,6 +826,7 @@ public sealed class MxGatewaySession : IAsyncDisposable
///
/// Closes the session and releases resources.
///
+ /// A task that represents the asynchronous operation.
public async ValueTask DisposeAsync()
{
await CloseAsync().ConfigureAwait(false);
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxStatusProxyExtensions.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxStatusProxyExtensions.cs
index 5441431..88cd6ad 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxStatusProxyExtensions.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxStatusProxyExtensions.cs
@@ -7,6 +7,7 @@ public static class MxStatusProxyExtensions
{
/// Returns whether the status indicates success (success flag set and category is Ok).
/// The status to check.
+ /// true if the status is successful; false otherwise.
public static bool IsSuccess(this MxStatusProxy status)
{
ArgumentNullException.ThrowIfNull(status);
@@ -17,6 +18,7 @@ public static class MxStatusProxyExtensions
/// Returns a formatted summary of the status for diagnostic output.
/// The status to summarize.
+ /// A human-readable string combining category, source, detail, and diagnostic text.
public static string ToDiagnosticSummary(this MxStatusProxy status)
{
ArgumentNullException.ThrowIfNull(status);
diff --git a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxValueExtensions.cs b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxValueExtensions.cs
index 4f047bf..77c9258 100644
--- a/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxValueExtensions.cs
+++ b/clients/dotnet/ZB.MOM.WW.MxGateway.Client/MxValueExtensions.cs
@@ -14,6 +14,7 @@ public static class MxValueExtensions
/// Converts a boolean value to an MxValue with MxDataType.Boolean.
///
/// Scalar boolean value to wrap.
+ /// An with MxDataType.Boolean.
public static MxValue ToMxValue(this bool value)
{
return new MxValue
@@ -28,6 +29,7 @@ public static class MxValueExtensions
/// Converts a 32-bit integer value to an MxValue with MxDataType.Integer.
///
/// 32-bit integer value to wrap.
+ /// An with MxDataType.Integer.
public static MxValue ToMxValue(this int value)
{
return new MxValue
@@ -42,6 +44,7 @@ public static class MxValueExtensions
/// Converts a 64-bit integer value to an MxValue with MxDataType.Integer.
///
/// 64-bit integer value to wrap.
+ /// An with MxDataType.Integer.
public static MxValue ToMxValue(this long value)
{
return new MxValue
@@ -56,6 +59,7 @@ public static class MxValueExtensions
/// Converts a single-precision floating-point value to an MxValue with MxDataType.Float.
///
/// Single-precision floating-point value to wrap.
+ /// An with MxDataType.Float.
public static MxValue ToMxValue(this float value)
{
return new MxValue
@@ -70,6 +74,7 @@ public static class MxValueExtensions
/// Converts a double-precision floating-point value to an MxValue with MxDataType.Double.
///
/// Double-precision floating-point value to wrap.
+ /// An with MxDataType.Double.
public static MxValue ToMxValue(this double value)
{
return new MxValue
@@ -84,6 +89,7 @@ public static class MxValueExtensions
/// Converts a string value to an MxValue with MxDataType.String.
///
/// String value to wrap.
+ /// An with MxDataType.String.
public static MxValue ToMxValue(this string value)
{
ArgumentNullException.ThrowIfNull(value);
@@ -100,6 +106,7 @@ public static class MxValueExtensions
/// Converts a DateTimeOffset value to an MxValue with MxDataType.Time.
///
/// DateTimeOffset value to wrap.
+ /// An with MxDataType.Time.
public static MxValue ToMxValue(this DateTimeOffset value)
{
return new MxValue
@@ -114,6 +121,7 @@ public static class MxValueExtensions
/// Converts a DateTime value to an MxValue with MxDataType.Time.
///
/// DateTime value to wrap.
+ /// An with MxDataType.Time.
public static MxValue ToMxValue(this DateTime value)
{
return new DateTimeOffset(
@@ -127,6 +135,7 @@ public static class MxValueExtensions
/// Converts a boolean array to an MxValue with MxDataType.Boolean.
///
/// Array of boolean values to wrap.
+ /// An with MxDataType.Boolean and an array payload.
public static MxValue ToMxValue(this IReadOnlyList values)
{
ArgumentNullException.ThrowIfNull(values);
@@ -145,6 +154,7 @@ public static class MxValueExtensions
/// Converts a 32-bit integer array to an MxValue with MxDataType.Integer.
///
/// Array of 32-bit integer values to wrap.
+ /// An with MxDataType.Integer and an array payload.
public static MxValue ToMxValue(this IReadOnlyList values)
{
ArgumentNullException.ThrowIfNull(values);
@@ -163,6 +173,7 @@ public static class MxValueExtensions
/// Converts a 64-bit integer array to an MxValue with MxDataType.Integer.
///
/// Array of 64-bit integer values to wrap.
+ /// An with MxDataType.Integer and an array payload.
public static MxValue ToMxValue(this IReadOnlyList values)
{
ArgumentNullException.ThrowIfNull(values);
@@ -181,6 +192,7 @@ public static class MxValueExtensions
/// Converts a single-precision floating-point array to an MxValue with MxDataType.Float.
///
/// Array of single-precision floating-point values to wrap.
+ /// An with MxDataType.Float and an array payload.
public static MxValue ToMxValue(this IReadOnlyList values)
{
ArgumentNullException.ThrowIfNull(values);
@@ -199,6 +211,7 @@ public static class MxValueExtensions
/// Converts a double-precision floating-point array to an MxValue with MxDataType.Double.
///
/// Array of double-precision floating-point values to wrap.
+ /// An with MxDataType.Double and an array payload.
public static MxValue ToMxValue(this IReadOnlyList values)
{
ArgumentNullException.ThrowIfNull(values);
@@ -217,6 +230,7 @@ public static class MxValueExtensions
/// Converts a string array to an MxValue with MxDataType.String.
///
/// Array of string values to wrap.
+ /// An with MxDataType.String and an array payload.
public static MxValue ToMxValue(this IReadOnlyList values)
{
ArgumentNullException.ThrowIfNull(values);
@@ -235,6 +249,7 @@ public static class MxValueExtensions
/// Converts a DateTimeOffset array to an MxValue with MxDataType.Time.
///
/// Array of DateTimeOffset values to wrap.
+ /// An with MxDataType.Time and an array payload.
public static MxValue ToMxValue(this IReadOnlyList values)
{
ArgumentNullException.ThrowIfNull(values);
@@ -253,6 +268,7 @@ public static class MxValueExtensions
/// Gets the projection kind (field name) of the given MxValue's current oneof value.
///
/// The MxValue whose oneof projection kind is returned.
+ /// The JSON field name of the active oneof case, or "nullValue"/"unspecified" for null/unset values.
public static string GetProjectionKind(this MxValue value)
{
ArgumentNullException.ThrowIfNull(value);
@@ -276,6 +292,7 @@ public static class MxValueExtensions
/// Converts an MxValue to a CLR object; returns the boxed value or null for null MxValues.
///
/// The MxValue to convert.
+ /// The boxed CLR value, or null if the MxValue represents a null.
public static object? ToClrValue(this MxValue value)
{
ArgumentNullException.ThrowIfNull(value);
@@ -299,6 +316,7 @@ public static class MxValueExtensions
/// Converts an MxArray to a CLR array; returns null if the array does not have a known element type.
///
/// The MxArray to convert.
+ /// A CLR array of the appropriate element type, or null for unknown element types.
public static object? ToClrArrayValue(this MxArray array)
{
ArgumentNullException.ThrowIfNull(array);
@@ -328,6 +346,7 @@ public static class MxValueExtensions
/// Variant type string (e.g., "VT_BSTR").
/// Diagnostic string describing the raw value.
/// Optional MXAccess data type override.
+ /// An with MxDataType.Unknown and the raw byte payload.
public static MxValue ToRawMxValue(
byte[] value,
string variantType,
diff --git a/src/ZB.MOM.WW.MxGateway.IntegrationTests/DashboardLdapLiveTests.cs b/src/ZB.MOM.WW.MxGateway.IntegrationTests/DashboardLdapLiveTests.cs
index 0d2d39a..46ddd0e 100644
--- a/src/ZB.MOM.WW.MxGateway.IntegrationTests/DashboardLdapLiveTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.IntegrationTests/DashboardLdapLiveTests.cs
@@ -14,6 +14,7 @@ namespace ZB.MOM.WW.MxGateway.IntegrationTests;
public sealed class DashboardLdapLiveTests
{
/// Verifies that an admin user in the GwAdmin group authenticates successfully.
+ /// A task that represents the asynchronous operation.
[LiveLdapFact]
public async Task AuthenticateAsync_AdminInGwAdminGroup_Succeeds()
{
@@ -42,6 +43,7 @@ public sealed class DashboardLdapLiveTests
}
/// Verifies that a readonly user without GwAdmin group fails to authenticate.
+ /// A task that represents the asynchronous operation.
[LiveLdapFact]
public async Task AuthenticateAsync_ReadOnlyUserMissingGwAdminGroup_Fails()
{
@@ -58,6 +60,7 @@ public sealed class DashboardLdapLiveTests
}
/// Verifies that authentication with wrong password fails without leaking the password.
+ /// A task that represents the asynchronous operation.
[LiveLdapFact]
public async Task AuthenticateAsync_AdminWithWrongPassword_FailsWithoutLeakingPassword()
{
@@ -77,6 +80,7 @@ public sealed class DashboardLdapLiveTests
}
/// Verifies that authentication with unknown username fails.
+ /// A task that represents the asynchronous operation.
[LiveLdapFact]
public async Task AuthenticateAsync_UnknownUsername_Fails()
{
@@ -94,6 +98,7 @@ public sealed class DashboardLdapLiveTests
}
/// Verifies that authentication fails gracefully when the server is unreachable.
+ /// A task that represents the asynchronous operation.
[LiveLdapFact]
public async Task AuthenticateAsync_ServerUnreachable_FailsWithoutThrowing()
{
diff --git a/src/ZB.MOM.WW.MxGateway.IntegrationTests/Galaxy/GalaxyRepositoryLiveTests.cs b/src/ZB.MOM.WW.MxGateway.IntegrationTests/Galaxy/GalaxyRepositoryLiveTests.cs
index 9ffc4bd..d727943 100644
--- a/src/ZB.MOM.WW.MxGateway.IntegrationTests/Galaxy/GalaxyRepositoryLiveTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.IntegrationTests/Galaxy/GalaxyRepositoryLiveTests.cs
@@ -7,6 +7,7 @@ namespace ZB.MOM.WW.MxGateway.IntegrationTests.Galaxy;
public sealed class GalaxyRepositoryLiveTests
{
/// Verifies that the Galaxy Repository can establish a live connection to the ZB database.
+ /// A task that represents the asynchronous operation.
[LiveGalaxyRepositoryFact]
public async Task TestConnection_AgainstZb_Succeeds()
{
@@ -18,6 +19,7 @@ public sealed class GalaxyRepositoryLiveTests
}
/// Verifies that the last deploy time can be retrieved from the ZB database.
+ /// A task that represents the asynchronous operation.
[LiveGalaxyRepositoryFact]
public async Task GetLastDeployTime_AgainstZb_ReturnsTimestamp()
{
@@ -29,6 +31,7 @@ public sealed class GalaxyRepositoryLiveTests
}
/// Verifies that the hierarchy can be retrieved from the ZB database.
+ /// A task that represents the asynchronous operation.
[LiveGalaxyRepositoryFact]
public async Task GetHierarchy_AgainstZb_ReturnsObjects()
{
@@ -46,6 +49,7 @@ public sealed class GalaxyRepositoryLiveTests
}
/// Verifies that object attributes can be retrieved from the ZB database.
+ /// A task that represents the asynchronous operation.
[LiveGalaxyRepositoryFact]
public async Task GetAttributes_AgainstZb_ReturnsAtLeastOneAttribute()
{
diff --git a/src/ZB.MOM.WW.MxGateway.IntegrationTests/WorkerLiveMxAccessSmokeTests.cs b/src/ZB.MOM.WW.MxGateway.IntegrationTests/WorkerLiveMxAccessSmokeTests.cs
index 4464c52..aa38648 100644
--- a/src/ZB.MOM.WW.MxGateway.IntegrationTests/WorkerLiveMxAccessSmokeTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.IntegrationTests/WorkerLiveMxAccessSmokeTests.cs
@@ -30,6 +30,7 @@ public sealed class WorkerLiveMxAccessSmokeTests(ITestOutputHelper output)
///
/// Verifies that a gateway session can register, add item, advise, and stream events from live MXAccess.
///
+ /// A task that represents the asynchronous operation.
[LiveMxAccessFact]
public async Task GatewaySession_WithLiveWorker_RegistersAdvisesStreamsDataAndCloses()
{
@@ -119,6 +120,7 @@ public sealed class WorkerLiveMxAccessSmokeTests(ITestOutputHelper output)
/// and that the worker emits a matching event
/// — the proof of round-trip the cross-language client e2e runner relies on.
///
+ /// A task that represents the asynchronous operation.
[LiveMxAccessFact]
public async Task GatewaySession_WithLiveWorker_WritesValueToAdvisedItem()
{
@@ -235,6 +237,7 @@ public sealed class WorkerLiveMxAccessSmokeTests(ITestOutputHelper output)
/// Verifies that an AddItem against an invalid server handle surfaces the MXAccess failure
/// without faulting the gateway transport, exercising the invalid-handle parity path.
///
+ /// A task that represents the asynchronous operation.
[LiveMxAccessFact]
public async Task GatewaySession_WithLiveWorker_InvalidHandleCommand_SurfacesFailureWithoutTransportFault()
{
@@ -293,6 +296,7 @@ public sealed class WorkerLiveMxAccessSmokeTests(ITestOutputHelper output)
/// OnDataChange events for the un-advised item. Exercises the lifecycle-ordering
/// parity CLAUDE.md singles out as a "do not synthesize" rule.
///
+ /// A task that represents the asynchronous operation.
[LiveMxAccessFact]
public async Task GatewaySession_WithLiveWorker_UnadviseRemoveItemUnregister_TeardownOrderingParity()
{
@@ -437,6 +441,7 @@ public sealed class WorkerLiveMxAccessSmokeTests(ITestOutputHelper output)
/// parity surface the gateway must not "fix" — the test asserts the reply kind and
/// protocol status, not a fabricated outcome.
///
+ /// A task that represents the asynchronous operation.
[LiveMxAccessFact]
public async Task GatewaySession_WithLiveWorker_WriteSecured_AuthenticatedRoundTripParity()
{
@@ -568,6 +573,7 @@ public sealed class WorkerLiveMxAccessSmokeTests(ITestOutputHelper output)
/// must observe the abnormal exit, transition the session, and surface a non-empty
/// fault description rather than hanging or crashing.
///
+ /// A task that represents the asynchronous operation.
[LiveMxAccessFact]
public async Task GatewaySession_WithLiveWorker_AbnormalWorkerExit_MarksSessionFaulted()
{
@@ -1114,6 +1120,7 @@ public sealed class WorkerLiveMxAccessSmokeTests(ITestOutputHelper output)
///
/// The session identifier.
/// The session if found; otherwise null.
+ /// True if the session was found; otherwise false.
public bool TryGetSession(string sessionId, [MaybeNullWhen(false)] out GatewaySession session)
{
return _registry.TryGet(sessionId, out session);
@@ -1122,6 +1129,7 @@ public sealed class WorkerLiveMxAccessSmokeTests(ITestOutputHelper output)
///
/// Disposes the fixture resources and closes all sessions.
///
+ /// A task that represents the asynchronous dispose operation.
public async ValueTask DisposeAsync()
{
foreach (GatewaySession session in _registry.Snapshot())
@@ -1192,6 +1200,7 @@ public sealed class WorkerLiveMxAccessSmokeTests(ITestOutputHelper output)
/// Records the message and signals any pending waiter.
///
/// The message to write.
+ /// A task that represents the asynchronous operation.
public Task WriteAsync(T message)
{
lock (syncRoot)
@@ -1374,7 +1383,9 @@ public sealed class WorkerLiveMxAccessSmokeTests(ITestOutputHelper output)
return workerProcess;
}
- ///
+ /// Waits for all recorded worker processes to exit within the specified timeout.
+ /// Maximum time to wait for each process to exit.
+ /// A task that represents the asynchronous operation.
public async Task WaitForProcessesAsync(TimeSpan timeout)
{
foreach (TestWorkerProcess process in processes)
@@ -1454,7 +1465,7 @@ public sealed class WorkerLiveMxAccessSmokeTests(ITestOutputHelper output)
process.Kill(entireProcessTree);
}
- ///
+ /// Releases the wrapped process resources.
public void Dispose()
{
process.Dispose();
@@ -1466,13 +1477,15 @@ public sealed class WorkerLiveMxAccessSmokeTests(ITestOutputHelper output)
///
private sealed class TestOutputLoggerProvider(ITestOutputHelper output) : ILoggerProvider
{
- ///
+ /// Creates a logger that writes to the test output helper for the given category.
+ /// The logger category name.
+ /// A logger that forwards to the test output helper.
public ILogger CreateLogger(string categoryName)
{
return new TestOutputLogger(output, categoryName);
}
- ///
+ /// Releases resources held by the provider (no-op for this test double).
public void Dispose()
{
}
@@ -1485,20 +1498,31 @@ public sealed class WorkerLiveMxAccessSmokeTests(ITestOutputHelper output)
ITestOutputHelper output,
string categoryName) : ILogger
{
- ///
+ /// Begins a log scope; returns null as this test logger does not support scopes.
+ /// The state object for the scope.
+ /// The type of the state object.
+ /// Always null.
public IDisposable? BeginScope(TState state)
where TState : notnull
{
return null;
}
- ///
+ /// Returns true for log levels at or above .
+ /// The log level to check.
+ /// True if the log level is enabled.
public bool IsEnabled(LogLevel logLevel)
{
return logLevel >= LogLevel.Information;
}
- ///
+ /// Writes a log entry to the test output helper.
+ /// The log level.
+ /// The event identifier.
+ /// The state object to log.
+ /// Optional exception associated with the log entry.
+ /// Function to format the state and exception into a string.
+ /// The type of the state object.
public void Log(
LogLevel logLevel,
EventId eventId,
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Alarms/GatewayAlarmMonitor.cs b/src/ZB.MOM.WW.MxGateway.Server/Alarms/GatewayAlarmMonitor.cs
index 30461c9..ef0101a 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Alarms/GatewayAlarmMonitor.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Alarms/GatewayAlarmMonitor.cs
@@ -688,6 +688,7 @@ public sealed class GatewayAlarmMonitor : BackgroundService, IGatewayAlarmServic
/// Determines whether the alarm reference matches this subscriber's filter.
/// The alarm reference to match.
+ /// True if the reference starts with this subscriber's prefix or no prefix is set.
public bool Matches(string reference)
{
return prefix.Length == 0 || reference.StartsWith(prefix, StringComparison.Ordinal);
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Alarms/IGatewayAlarmService.cs b/src/ZB.MOM.WW.MxGateway.Server/Alarms/IGatewayAlarmService.cs
index 268f7a7..69de41b 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Alarms/IGatewayAlarmService.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Alarms/IGatewayAlarmService.cs
@@ -46,6 +46,7 @@ public interface IGatewayAlarmService
///
/// Optional alarm-reference prefix scoping the feed.
/// Token that ends the subscription.
+ /// An async enumerable of alarm feed messages.
IAsyncEnumerable StreamAsync(
string? alarmFilterPrefix,
CancellationToken cancellationToken);
@@ -57,6 +58,7 @@ public interface IGatewayAlarmService
///
/// The acknowledge request.
/// Token to cancel the call.
+ /// A task that resolves to the acknowledge reply.
Task AcknowledgeAsync(
AcknowledgeAlarmRequest request,
CancellationToken cancellationToken);
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Configuration/GatewayOptionsValidator.cs b/src/ZB.MOM.WW.MxGateway.Server/Configuration/GatewayOptionsValidator.cs
index c228a5c..9109d8c 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Configuration/GatewayOptionsValidator.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Configuration/GatewayOptionsValidator.cs
@@ -9,11 +9,7 @@ public sealed class GatewayOptionsValidator : OptionsValidatorBase
- /// Validates gateway configuration options.
- ///
- /// The accumulator to record failures on.
- /// Gateway options to validate.
+ ///
protected override void Validate(ValidationBuilder builder, GatewayOptions options)
{
ValidateAuthentication(options.Authentication, builder);
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Configuration/IGatewayConfigurationProvider.cs b/src/ZB.MOM.WW.MxGateway.Server/Configuration/IGatewayConfigurationProvider.cs
index d4a1275..d47000e 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Configuration/IGatewayConfigurationProvider.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Configuration/IGatewayConfigurationProvider.cs
@@ -8,5 +8,6 @@ public interface IGatewayConfigurationProvider
///
/// Returns the validated and effective gateway configuration.
///
+ /// The with validated defaults applied.
EffectiveGatewayConfiguration GetEffectiveConfiguration();
}
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Components/DashboardPageBase.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Components/DashboardPageBase.cs
index f323bd4..28fc160 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Components/DashboardPageBase.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Components/DashboardPageBase.cs
@@ -38,7 +38,8 @@ public abstract class DashboardPageBase : ComponentBase, IAsyncDisposable
await ConnectHubAsync().ConfigureAwait(false);
}
- ///
+ /// Disposes the SignalR hub connection and suppresses finalization.
+ /// A task that represents the asynchronous operation.
public async ValueTask DisposeAsync()
{
if (_hub is not null)
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardApiKeyAuthorization.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardApiKeyAuthorization.cs
index cc81219..8f8532f 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardApiKeyAuthorization.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardApiKeyAuthorization.cs
@@ -6,6 +6,7 @@ public sealed class DashboardApiKeyAuthorization
{
/// Determines whether the user can manage API keys.
/// The authenticated user principal.
+ /// True if the user is an authenticated admin; otherwise false.
public bool CanManage(ClaimsPrincipal user)
{
if (user.Identity?.IsAuthenticated != true)
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardApiKeyManagementService.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardApiKeyManagementService.cs
index 86a241d..1963d7a 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardApiKeyManagementService.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardApiKeyManagementService.cs
@@ -20,17 +20,13 @@ public sealed class DashboardApiKeyManagementService(
private const string UnauthorizedMessage = "Sign in with an authorized LDAP account to manage API keys.";
private const string PepperUnavailableMarker = "pepper unavailable";
- /// Determines whether the user can manage API keys.
- /// The authenticated user principal.
+ ///
public bool CanManage(ClaimsPrincipal user)
{
return authorization.CanManage(user);
}
- /// Creates an API key asynchronously.
- /// The authenticated user principal.
- /// The request payload.
- /// Token to observe for cancellation.
+ ///
public async Task CreateAsync(
ClaimsPrincipal user,
DashboardApiKeyManagementRequest request,
@@ -82,10 +78,7 @@ public sealed class DashboardApiKeyManagementService(
}
}
- /// Revokes an API key asynchronously.
- /// The authenticated user principal.
- /// The API key identifier.
- /// Token to observe for cancellation.
+ ///
public async Task RevokeAsync(
ClaimsPrincipal user,
string keyId,
@@ -120,10 +113,7 @@ public sealed class DashboardApiKeyManagementService(
: DashboardApiKeyManagementResult.Fail("API key was not found or is already revoked.");
}
- /// Rotates an API key secret asynchronously.
- /// The authenticated user principal.
- /// The API key identifier.
- /// Token to observe for cancellation.
+ ///
public async Task RotateAsync(
ClaimsPrincipal user,
string keyId,
@@ -170,10 +160,7 @@ public sealed class DashboardApiKeyManagementService(
}
}
- /// Deletes a revoked API key asynchronously.
- /// The authenticated user principal.
- /// The API key identifier.
- /// Token to observe for cancellation.
+ ///
public async Task DeleteAsync(
ClaimsPrincipal user,
string keyId,
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardAuthenticationResult.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardAuthenticationResult.cs
index b656c79..e21faa9 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardAuthenticationResult.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardAuthenticationResult.cs
@@ -23,6 +23,7 @@ public sealed record DashboardAuthenticationResult(
/// Creates a successful authentication result.
///
/// Authenticated principal.
+ /// A successful wrapping the principal.
public static DashboardAuthenticationResult Success(ClaimsPrincipal principal)
{
return new DashboardAuthenticationResult(true, principal, null);
@@ -32,6 +33,7 @@ public sealed record DashboardAuthenticationResult(
/// Creates a failed authentication result.
///
/// Diagnostic message describing the failure.
+ /// A failed with the given message.
public static DashboardAuthenticationResult Fail(string failureMessage)
{
return new DashboardAuthenticationResult(false, null, failureMessage);
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardConnectionStringDisplay.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardConnectionStringDisplay.cs
index b0f1f2d..2e54879 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardConnectionStringDisplay.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardConnectionStringDisplay.cs
@@ -6,6 +6,7 @@ public static class DashboardConnectionStringDisplay
{
/// Returns a sanitized Galaxy Repository connection string for display.
/// The connection string to sanitize.
+ /// A sanitized connection string with credentials removed, or "[invalid connection string]" if parsing fails.
public static string GalaxyRepositoryConnectionString(string connectionString)
{
try
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardGalaxyProjector.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardGalaxyProjector.cs
index a87e0c4..693ee90 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardGalaxyProjector.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardGalaxyProjector.cs
@@ -7,6 +7,7 @@ internal static class DashboardGalaxyProjector
{
/// Projects the cache entry to a dashboard Galaxy summary.
/// The Galaxy hierarchy cache entry.
+ /// The precomputed from the cache entry.
public static DashboardGalaxySummary Project(GalaxyHierarchyCacheEntry entry)
{
return entry.DashboardSummary;
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardGroupRoleMapper.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardGroupRoleMapper.cs
index 946c7a1..72ea782 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardGroupRoleMapper.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardGroupRoleMapper.cs
@@ -17,7 +17,10 @@ namespace ZB.MOM.WW.MxGateway.Server.Dashboard;
public sealed class DashboardGroupRoleMapper(IOptions options)
: IGroupRoleMapper
{
- ///
+ /// Maps LDAP group memberships to dashboard roles using the configured group-to-role rules.
+ /// The list of LDAP group names or distinguished names for the authenticated user.
+ /// Token to cancel the asynchronous operation.
+ /// A task that resolves to the role mapping for the supplied groups.
public Task> MapAsync(
IReadOnlyList groups,
CancellationToken ct)
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardGroupRoleMapping.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardGroupRoleMapping.cs
index 2fa1029..4a7a9e2 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardGroupRoleMapping.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardGroupRoleMapping.cs
@@ -16,6 +16,7 @@ internal static class DashboardGroupRoleMapping
///
/// The collection of LDAP groups the user belongs to.
/// The mapping from group names to dashboard role names.
+ /// The distinct set of dashboard roles matched from the user's groups.
internal static IReadOnlyList MapGroupsToRoles(
IEnumerable groups,
IReadOnlyDictionary groupToRole)
@@ -61,6 +62,7 @@ internal static class DashboardGroupRoleMapping
/// Extracts the first RDN value from a distinguished name.
/// The LDAP distinguished name.
+ /// The value portion of the first RDN component, or the full string if no = is found.
internal static string ExtractFirstRdnValue(string distinguishedName)
{
int equalsIndex = distinguishedName.IndexOf('=');
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardLiveDataService.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardLiveDataService.cs
index 9e7b4b2..86d47fd 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardLiveDataService.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardLiveDataService.cs
@@ -192,7 +192,8 @@ public sealed class DashboardLiveDataService : IDashboardLiveDataService, IAsync
}
}
- ///
+ /// Releases resources and closes the associated gateway session.
+ /// A task that represents the asynchronous dispose operation.
public async ValueTask DisposeAsync()
{
if (_disposed)
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardServiceCollectionExtensions.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardServiceCollectionExtensions.cs
index 806fe41..7982592 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardServiceCollectionExtensions.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardServiceCollectionExtensions.cs
@@ -23,6 +23,7 @@ public static class DashboardServiceCollectionExtensions
/// Application configuration, used to bind the shared LDAP provider's options
/// from the MxGateway:Ldap section.
///
+ /// The collection for chaining.
public static IServiceCollection AddGatewayDashboard(
this IServiceCollection services,
IConfiguration configuration)
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardSessionAdminResult.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardSessionAdminResult.cs
index 136e92a..53fa124 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardSessionAdminResult.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardSessionAdminResult.cs
@@ -6,6 +6,7 @@ public sealed record DashboardSessionAdminResult(
{
/// Creates a successful result with the given message.
/// The result message.
+ /// A with Succeeded set to true.
public static DashboardSessionAdminResult Success(string message)
{
return new DashboardSessionAdminResult(true, message);
@@ -13,6 +14,7 @@ public sealed record DashboardSessionAdminResult(
/// Creates a failed result with the given message.
/// The result message.
+ /// A with Succeeded set to false.
public static DashboardSessionAdminResult Fail(string message)
{
return new DashboardSessionAdminResult(false, message);
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardSnapshotService.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardSnapshotService.cs
index 290879c..28dcae5 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardSnapshotService.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/DashboardSnapshotService.cs
@@ -65,10 +65,7 @@ public sealed class DashboardSnapshotService : IDashboardSnapshotService
_logger = logger ?? NullLogger.Instance;
}
- ///
- /// Gets a current dashboard snapshot of gateway state.
- ///
- /// Dashboard snapshot.
+ ///
public DashboardSnapshot GetSnapshot()
{
DateTimeOffset generatedAt = _timeProvider.GetUtcNow();
@@ -100,11 +97,7 @@ public sealed class DashboardSnapshotService : IDashboardSnapshotService
Galaxy: DashboardGalaxyProjector.Project(_galaxyHierarchyCache.Current));
}
- ///
- /// Watches dashboard snapshots at regular intervals asynchronously.
- ///
- /// Cancellation token.
- /// Async enumerable of dashboard snapshots.
+ ///
public async IAsyncEnumerable WatchSnapshotsAsync(
[EnumeratorCancellation] CancellationToken cancellationToken)
{
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/HubTokenService.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/HubTokenService.cs
index 52bd9af..3a4f3a6 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/HubTokenService.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/HubTokenService.cs
@@ -40,6 +40,7 @@ public sealed class HubTokenService
/// Issues a bearer token carrying the user's identity and roles.
/// The claims principal representing the user.
+ /// The time-limited bearer token string.
public string Issue(ClaimsPrincipal user)
{
ArgumentNullException.ThrowIfNull(user);
@@ -52,6 +53,7 @@ public sealed class HubTokenService
/// Validates a token and returns the equivalent claims principal; null when invalid or expired.
/// The token string to validate.
+ /// The claims principal if the token is valid, or null if invalid or expired.
public ClaimsPrincipal? Validate(string? token)
{
if (string.IsNullOrEmpty(token))
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Hubs/DashboardEventBroadcaster.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Hubs/DashboardEventBroadcaster.cs
index 2e63b08..91c0a3a 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Hubs/DashboardEventBroadcaster.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Hubs/DashboardEventBroadcaster.cs
@@ -14,9 +14,7 @@ public sealed class DashboardEventBroadcaster(
IHubContext hubContext,
ILogger logger) : IDashboardEventBroadcaster
{
- /// Publishes an MX event to connected dashboard clients.
- /// The session identifier.
- /// The MX event to publish.
+ ///
public void Publish(string sessionId, MxEvent mxEvent)
{
if (string.IsNullOrEmpty(sessionId) || mxEvent is null)
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Hubs/EventsHub.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Hubs/EventsHub.cs
index 382dcad..2db9dfd 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Hubs/EventsHub.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/Hubs/EventsHub.cs
@@ -49,6 +49,7 @@ public sealed class EventsHub : Hub
/// dedicated authorization policy applied to the hub method itself.
///
/// Session id to subscribe the caller to.
+ /// A task that represents the asynchronous operation.
public Task SubscribeSession(string sessionId)
{
if (string.IsNullOrWhiteSpace(sessionId))
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/IDashboardAuthenticator.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/IDashboardAuthenticator.cs
index 5496f4d..546fd50 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/IDashboardAuthenticator.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/IDashboardAuthenticator.cs
@@ -11,6 +11,7 @@ public interface IDashboardAuthenticator
/// Username to authenticate.
/// Password to authenticate.
/// Token to cancel the asynchronous operation.
+ /// A task that resolves to the authentication result.
Task AuthenticateAsync(
string? username,
string? password,
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/IDashboardBrowseService.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/IDashboardBrowseService.cs
index 53becb9..3693d27 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/IDashboardBrowseService.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/IDashboardBrowseService.cs
@@ -12,11 +12,13 @@ public interface IDashboardBrowseService
{
/// Returns root browse nodes (objects with no parent).
/// Filter arguments forwarded to the projector.
+ /// The root-level browse result.
BrowseLevelResult GetRoots(BrowseFilterArgs filter);
/// Returns the direct children of the given parent gobject id.
/// The Galaxy gobject id of the parent to expand.
/// Filter arguments forwarded to the projector.
+ /// The children browse result for the specified parent.
BrowseLevelResult GetChildren(int parentGobjectId, BrowseFilterArgs filter);
/// Current Galaxy cache sequence. Bumps after each successful refresh.
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/IDashboardSnapshotService.cs b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/IDashboardSnapshotService.cs
index ca33819..1156d12 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Dashboard/IDashboardSnapshotService.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Dashboard/IDashboardSnapshotService.cs
@@ -8,11 +8,13 @@ public interface IDashboardSnapshotService
///
/// Gets the current dashboard snapshot.
///
+ /// The most recent .
DashboardSnapshot GetSnapshot();
///
/// Watches for changes to the dashboard state as an async enumerable.
///
/// Token to cancel the asynchronous operation.
+ /// An async sequence of values as state changes.
IAsyncEnumerable WatchSnapshotsAsync(CancellationToken cancellationToken);
}
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Diagnostics/AuthStoreHealthCheck.cs b/src/ZB.MOM.WW.MxGateway.Server/Diagnostics/AuthStoreHealthCheck.cs
index 30766a5..5c452c9 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Diagnostics/AuthStoreHealthCheck.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Diagnostics/AuthStoreHealthCheck.cs
@@ -12,9 +12,15 @@ public sealed class AuthStoreHealthCheck : IHealthCheck
{
private readonly AuthSqliteConnectionFactory _connectionFactory;
+ /// Initializes a new instance of with the given connection factory.
+ /// Factory for opening SQLite connections to the auth store.
public AuthStoreHealthCheck(AuthSqliteConnectionFactory connectionFactory) =>
_connectionFactory = connectionFactory ?? throw new ArgumentNullException(nameof(connectionFactory));
+ /// Runs a lightweight connectivity probe against the SQLite authentication store.
+ /// Health check context supplied by the framework.
+ /// Token to cancel the asynchronous operation.
+ /// A task that resolves to the health check result.
public async Task CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default)
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Diagnostics/GatewayLogRedactor.cs b/src/ZB.MOM.WW.MxGateway.Server/Diagnostics/GatewayLogRedactor.cs
index d04d2aa..cbe01a1 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Diagnostics/GatewayLogRedactor.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Diagnostics/GatewayLogRedactor.cs
@@ -19,6 +19,7 @@ public static class GatewayLogRedactor
/// Determines whether a command method bears credentials.
///
/// The command method name to check.
+ /// true if the method carries credentials; otherwise false.
public static bool IsCredentialBearingCommand(string? commandMethod)
{
return commandMethod is not null
@@ -29,6 +30,7 @@ public static class GatewayLogRedactor
/// Redacts the API key secret portion of a Bearer authorization header.
///
/// The authorization header value to redact.
+ /// The header with the secret portion replaced by , or the original if no key is detected.
public static string? RedactApiKey(string? authorizationHeader)
{
if (string.IsNullOrWhiteSpace(authorizationHeader))
@@ -62,6 +64,7 @@ public static class GatewayLogRedactor
/// Redacts the client identity if it contains an API key.
///
/// The client identity string to redact.
+ /// The redacted identity string, or the original if no key pattern is found.
public static string? RedactClientIdentity(string? clientIdentity)
{
if (string.IsNullOrWhiteSpace(clientIdentity))
@@ -80,6 +83,7 @@ public static class GatewayLogRedactor
/// The command method name to check for credentials.
/// The command value to redact.
/// Whether value logging is enabled.
+ /// The original value when logging is enabled and the command is not credential-bearing; otherwise .
public static object? RedactCommandValue(
string? commandMethod,
object? value,
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Diagnostics/GatewayLogScope.cs b/src/ZB.MOM.WW.MxGateway.Server/Diagnostics/GatewayLogScope.cs
index c80a2d4..b85df37 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Diagnostics/GatewayLogScope.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Diagnostics/GatewayLogScope.cs
@@ -8,6 +8,7 @@ public sealed record GatewayLogScope(
string? ClientIdentity = null)
{
/// Converts the log scope to a dictionary with redacted sensitive fields.
+ /// A dictionary of non-null scope properties with sensitive fields redacted.
public IReadOnlyDictionary ToDictionary()
{
Dictionary values = [];
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Diagnostics/GatewayRequestLoggingMiddlewareExtensions.cs b/src/ZB.MOM.WW.MxGateway.Server/Diagnostics/GatewayRequestLoggingMiddlewareExtensions.cs
index 84a0af0..fd1b03a 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Diagnostics/GatewayRequestLoggingMiddlewareExtensions.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Diagnostics/GatewayRequestLoggingMiddlewareExtensions.cs
@@ -19,6 +19,7 @@ public static class GatewayRequestLoggingMiddlewareExtensions
/// Adds gateway request logging scope middleware that reads correlation headers and redacts sensitive data.
/// Application builder.
+ /// The instance for chaining.
public static IApplicationBuilder UseGatewayRequestLoggingScope(this IApplicationBuilder app)
{
ArgumentNullException.ThrowIfNull(app);
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Galaxy/GalaxyBrowseProjector.cs b/src/ZB.MOM.WW.MxGateway.Server/Galaxy/GalaxyBrowseProjector.cs
index 1768fb3..0738e7a 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Galaxy/GalaxyBrowseProjector.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Galaxy/GalaxyBrowseProjector.cs
@@ -27,6 +27,7 @@ public static class GalaxyBrowseProjector
/// Optional API-key browse-subtree constraints.
/// Zero-based offset into the filtered child list.
/// Maximum number of children to return.
+ /// A page of children with total count and filter signature.
public static GalaxyBrowseChildrenResult ProjectChildren(
GalaxyHierarchyCacheEntry entry,
BrowseChildrenRequest request,
@@ -71,6 +72,7 @@ public static class GalaxyBrowseProjector
///
/// The Galaxy hierarchy cache entry to query.
/// The browse-children request.
+ /// The resolved parent gobject id, or 0 for roots.
public static int ResolveParentId(GalaxyHierarchyCacheEntry entry, BrowseChildrenRequest request)
{
switch (request.ParentCase)
@@ -257,6 +259,7 @@ public static class GalaxyBrowseProjector
/// The browse-children request.
/// Optional API-key browse-subtree constraints.
/// Resolved parent gobject id (0 for roots).
+ /// A hex-encoded SHA-256 prefix that uniquely identifies the filter combination.
public static string ComputeFilterSignature(
BrowseChildrenRequest request,
IReadOnlyList? browseSubtreeGlobs,
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Galaxy/GalaxyDeployNotifier.cs b/src/ZB.MOM.WW.MxGateway.Server/Galaxy/GalaxyDeployNotifier.cs
index f7ae0a0..d6cfee6 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Galaxy/GalaxyDeployNotifier.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Galaxy/GalaxyDeployNotifier.cs
@@ -20,9 +20,7 @@ public sealed class GalaxyDeployNotifier : IGalaxyDeployNotifier
private readonly ConcurrentDictionary> _subscribers = new();
private GalaxyDeployEventInfo? _latest;
- ///
- /// The most recent deploy event, or null if none has been published.
- ///
+ ///
public GalaxyDeployEventInfo? Latest => Volatile.Read(ref _latest);
///
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Galaxy/GalaxyGlobMatcher.cs b/src/ZB.MOM.WW.MxGateway.Server/Galaxy/GalaxyGlobMatcher.cs
index 2ec139e..8b79e0a 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Galaxy/GalaxyGlobMatcher.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Galaxy/GalaxyGlobMatcher.cs
@@ -46,6 +46,7 @@ public static class GalaxyGlobMatcher
/// Determines whether a value matches a glob pattern (with * and ? wildcards).
/// The value to test against the glob pattern.
/// The glob pattern with * and ? wildcards.
+ /// if the value matches the glob pattern; otherwise .
public static bool IsMatch(string value, string glob)
{
if (string.IsNullOrWhiteSpace(glob))
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Galaxy/GalaxyHierarchyCache.cs b/src/ZB.MOM.WW.MxGateway.Server/Galaxy/GalaxyHierarchyCache.cs
index 8bafe52..0bbc7c0 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Galaxy/GalaxyHierarchyCache.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Galaxy/GalaxyHierarchyCache.cs
@@ -54,7 +54,7 @@ public sealed class GalaxyHierarchyCache : IGalaxyHierarchyCache
_snapshotStore = snapshotStore;
}
- /// Gets the current Galaxy hierarchy cache entry with projected status.
+ ///
public GalaxyHierarchyCacheEntry Current
{
get
@@ -74,9 +74,7 @@ public sealed class GalaxyHierarchyCache : IGalaxyHierarchyCache
}
}
- /// Refreshes the Galaxy hierarchy cache if the deploy time has advanced.
- /// Token to cancel the asynchronous operation.
- /// Asynchronous task representing the refresh operation.
+ ///
public async Task RefreshAsync(CancellationToken cancellationToken)
{
await _refreshGate.WaitAsync(cancellationToken).ConfigureAwait(false);
@@ -90,9 +88,7 @@ public sealed class GalaxyHierarchyCache : IGalaxyHierarchyCache
}
}
- /// Waits for the Galaxy hierarchy cache to complete its first load.
- /// Token to cancel the asynchronous operation.
- /// Asynchronous task representing the wait operation.
+ ///
public Task WaitForFirstLoadAsync(CancellationToken cancellationToken)
{
return _firstLoad.Task.WaitAsync(cancellationToken);
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Galaxy/GalaxyHierarchyProjector.cs b/src/ZB.MOM.WW.MxGateway.Server/Galaxy/GalaxyHierarchyProjector.cs
index d74df56..44b788f 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Galaxy/GalaxyHierarchyProjector.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Galaxy/GalaxyHierarchyProjector.cs
@@ -25,6 +25,7 @@ public static class GalaxyHierarchyProjector
/// The Galaxy hierarchy cache entry.
/// The discovery hierarchy request.
/// Optional glob patterns to filter browse subtrees.
+ /// The query result containing matching objects.
public static GalaxyHierarchyQueryResult Project(
GalaxyHierarchyCacheEntry entry,
DiscoverHierarchyRequest request,
@@ -44,6 +45,7 @@ public static class GalaxyHierarchyProjector
/// Optional glob patterns to filter browse subtrees.
/// The zero-based offset into the result set.
/// The maximum number of results to return.
+ /// The query result containing the requested page of matching objects.
public static GalaxyHierarchyQueryResult Project(
GalaxyHierarchyCacheEntry entry,
DiscoverHierarchyRequest request,
@@ -131,6 +133,7 @@ public static class GalaxyHierarchyProjector
/// Finds an object in the hierarchy by its tag address.
/// The Galaxy hierarchy cache entry.
/// The tag address to search for.
+ /// The matching Galaxy object, or null if not found.
public static GalaxyObject? FindObjectForTag(
GalaxyHierarchyCacheEntry entry,
string tagAddress)
@@ -148,6 +151,7 @@ public static class GalaxyHierarchyProjector
/// Finds an attribute in the hierarchy by its tag address.
/// The Galaxy hierarchy cache entry.
/// The tag address to search for.
+ /// The matching Galaxy attribute, or null if not found.
public static GalaxyAttribute? FindAttributeForTag(
GalaxyHierarchyCacheEntry entry,
string tagAddress)
@@ -165,6 +169,7 @@ public static class GalaxyHierarchyProjector
/// Gets the contained path for an object by its gobject ID.
/// The Galaxy hierarchy cache entry.
/// The Galaxy object ID.
+ /// The contained path string, or an empty string if the object is not found.
public static string GetContainedPath(
GalaxyHierarchyCacheEntry entry,
int gobjectId)
@@ -282,6 +287,7 @@ public static class GalaxyHierarchyProjector
/// Computes a stable filter signature for memoization purposes.
/// The discovery hierarchy request.
/// Optional glob patterns to filter browse subtrees.
+ /// A string key that uniquely identifies the combination of filter parameters.
public static string ComputeFilterSignature(
DiscoverHierarchyRequest request,
IReadOnlyList? browseSubtreeGlobs)
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Galaxy/GalaxyRepository.cs b/src/ZB.MOM.WW.MxGateway.Server/Galaxy/GalaxyRepository.cs
index db3c171..367885e 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Galaxy/GalaxyRepository.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Galaxy/GalaxyRepository.cs
@@ -15,8 +15,7 @@ namespace ZB.MOM.WW.MxGateway.Server.Galaxy;
///
public sealed class GalaxyRepository(GalaxyRepositoryOptions options) : IGalaxyRepository
{
- /// Tests the connection to the Galaxy Repository database.
- /// Token to cancel the asynchronous operation.
+ ///
public async Task TestConnectionAsync(CancellationToken ct = default)
{
try
@@ -31,8 +30,7 @@ public sealed class GalaxyRepository(GalaxyRepositoryOptions options) : IGalaxyR
catch (InvalidOperationException) { return false; }
}
- /// Retrieves the last deployment time from the Galaxy Repository.
- /// Token to cancel the asynchronous operation.
+ ///
public async Task GetLastDeployTimeAsync(CancellationToken ct = default)
{
using SqlConnection conn = new(options.ConnectionString);
@@ -43,8 +41,7 @@ public sealed class GalaxyRepository(GalaxyRepositoryOptions options) : IGalaxyR
return result is DateTime dt ? dt : null;
}
- /// Retrieves the complete hierarchy of Galaxy objects from the repository.
- /// Token to cancel the asynchronous operation.
+ ///
public async Task> GetHierarchyAsync(CancellationToken ct = default)
{
List rows = new();
@@ -81,8 +78,7 @@ public sealed class GalaxyRepository(GalaxyRepositoryOptions options) : IGalaxyR
return rows;
}
- /// Retrieves all attributes for Galaxy objects from the repository.
- /// Token to cancel the asynchronous operation.
+ ///
public async Task> GetAttributesAsync(CancellationToken ct = default)
{
List rows = new();
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Galaxy/IGalaxyHierarchyCache.cs b/src/ZB.MOM.WW.MxGateway.Server/Galaxy/IGalaxyHierarchyCache.cs
index 0737276..0428312 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Galaxy/IGalaxyHierarchyCache.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Galaxy/IGalaxyHierarchyCache.cs
@@ -13,6 +13,7 @@ public interface IGalaxyHierarchyCache
/// refresh.
///
/// Token to cancel the asynchronous operation.
+ /// A task that represents the asynchronous operation.
Task RefreshAsync(CancellationToken cancellationToken);
///
@@ -21,5 +22,6 @@ public interface IGalaxyHierarchyCache
/// very first request after gateway start.
///
/// Token to cancel the asynchronous operation.
+ /// A task that represents the asynchronous operation.
Task WaitForFirstLoadAsync(CancellationToken cancellationToken);
}
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Galaxy/IGalaxyHierarchySnapshotStore.cs b/src/ZB.MOM.WW.MxGateway.Server/Galaxy/IGalaxyHierarchySnapshotStore.cs
index 53556d5..93f1c33 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Galaxy/IGalaxyHierarchySnapshotStore.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Galaxy/IGalaxyHierarchySnapshotStore.cs
@@ -13,6 +13,7 @@ public interface IGalaxyHierarchySnapshotStore
///
/// The browse dataset to persist.
/// Token to cancel the asynchronous operation.
+ /// A task that represents the asynchronous save operation.
Task SaveAsync(GalaxyHierarchySnapshot snapshot, CancellationToken cancellationToken);
///
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Galaxy/IGalaxyRepository.cs b/src/ZB.MOM.WW.MxGateway.Server/Galaxy/IGalaxyRepository.cs
index 6621837..36b173c 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Galaxy/IGalaxyRepository.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Galaxy/IGalaxyRepository.cs
@@ -14,17 +14,21 @@ public interface IGalaxyRepository
{
/// Tests the connection to the Galaxy Repository database.
/// Token to cancel the asynchronous operation.
+ /// A task that resolves to if the connection succeeds; otherwise .
Task TestConnectionAsync(CancellationToken ct = default);
/// Retrieves the last deployment time from the Galaxy Repository.
/// Token to cancel the asynchronous operation.
+ /// A task that resolves to the last deploy time, or if not available.
Task GetLastDeployTimeAsync(CancellationToken ct = default);
/// Retrieves the complete hierarchy of Galaxy objects from the repository.
/// Token to cancel the asynchronous operation.
+ /// A task that resolves to the list of hierarchy rows.
Task> GetHierarchyAsync(CancellationToken ct = default);
/// Retrieves all attributes for Galaxy objects from the repository.
/// Token to cancel the asynchronous operation.
+ /// A task that resolves to the list of attribute rows.
Task> GetAttributesAsync(CancellationToken ct = default);
}
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Grpc/EventStreamService.cs b/src/ZB.MOM.WW.MxGateway.Server/Grpc/EventStreamService.cs
index a519f58..2f37f89 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Grpc/EventStreamService.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Grpc/EventStreamService.cs
@@ -18,12 +18,7 @@ public sealed class EventStreamService(
IDashboardEventBroadcaster dashboardEventBroadcaster,
ILogger logger) : IEventStreamService
{
- ///
- /// Streams events from a session to the client asynchronously.
- ///
- /// Stream events request.
- /// Cancellation token.
- /// Async enumerable of MX events.
+ ///
public async IAsyncEnumerable StreamEventsAsync(
StreamEventsRequest request,
[EnumeratorCancellation] CancellationToken cancellationToken)
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Grpc/GalaxyProtoMapper.cs b/src/ZB.MOM.WW.MxGateway.Server/Grpc/GalaxyProtoMapper.cs
index 5102709..bebd7b3 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Grpc/GalaxyProtoMapper.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Grpc/GalaxyProtoMapper.cs
@@ -13,6 +13,7 @@ public static class GalaxyProtoMapper
/// Maps Galaxy hierarchy and attribute rows to Galaxy object protos.
/// Hierarchy rows from Galaxy Repository.
/// Attribute rows from Galaxy Repository.
+ /// An enumerable of mapped Galaxy object protos.
public static IEnumerable MapHierarchy(
IReadOnlyList hierarchy,
IReadOnlyList attributes)
@@ -30,6 +31,7 @@ public static class GalaxyProtoMapper
/// Maps a Galaxy hierarchy row to a Galaxy object proto.
/// Hierarchy row from Galaxy Repository.
/// Attributes indexed by gobject ID.
+ /// The mapped Galaxy object proto.
public static GalaxyObject MapObject(
GalaxyHierarchyRow row,
IReadOnlyDictionary> attributesByGobjectId)
@@ -60,6 +62,7 @@ public static class GalaxyProtoMapper
/// Maps a Galaxy attribute row to a Galaxy attribute proto.
/// Attribute row from Galaxy Repository.
+ /// The mapped Galaxy attribute proto.
public static GalaxyAttribute MapAttribute(GalaxyAttributeRow row) => new()
{
AttributeName = row.AttributeName,
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Grpc/IEventStreamService.cs b/src/ZB.MOM.WW.MxGateway.Server/Grpc/IEventStreamService.cs
index ace7fce..9bc9892 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Grpc/IEventStreamService.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Grpc/IEventStreamService.cs
@@ -12,6 +12,7 @@ public interface IEventStreamService
///
/// Request payload.
/// Token to cancel the asynchronous operation.
+ /// An async enumerable of MXAccess events.
IAsyncEnumerable StreamEventsAsync(
StreamEventsRequest request,
CancellationToken cancellationToken);
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Grpc/MxAccessGatewayService.cs b/src/ZB.MOM.WW.MxGateway.Server/Grpc/MxAccessGatewayService.cs
index 362ad46..1d7303a 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Grpc/MxAccessGatewayService.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Grpc/MxAccessGatewayService.cs
@@ -162,15 +162,6 @@ public sealed class MxAccessGatewayService(
}
///
- ///
- /// Surfaces the public AcknowledgeAlarm RPC. Acknowledgement is
- /// session-less: the gateway routes it through the always-on
- /// monitor session. An
- /// alarm_full_reference that parses as a canonical GUID forwards
- /// to AcknowledgeAlarmCommand; a Provider!Group.Tag
- /// reference forwards to AcknowledgeAlarmByNameCommand; anything
- /// else returns an InvalidRequest diagnostic in the reply.
- ///
public override async Task AcknowledgeAlarm(
AcknowledgeAlarmRequest request,
ServerCallContext context)
@@ -193,14 +184,6 @@ public sealed class MxAccessGatewayService(
}
///
- ///
- /// Surfaces the public StreamAlarms RPC — the session-less central
- /// alarm feed. The stream opens with one active_alarm per
- /// currently-active alarm, then a single snapshot_complete, then
- /// a transition for every subsequent change. Served by the
- /// gateway's always-on monitor; any
- /// number of clients fan out from the single monitor.
- ///
public override async Task StreamAlarms(
StreamAlarmsRequest request,
IServerStreamWriter responseStream,
@@ -224,12 +207,6 @@ public sealed class MxAccessGatewayService(
}
///
- ///
- /// Snapshot of the active-alarm cache maintained by the gateway's
- /// always-on alarm monitor. Streams one
- /// per currently-active alarm and completes — no transitions are
- /// emitted. Use StreamAlarms for a live transition feed.
- ///
public override async Task QueryActiveAlarms(
QueryActiveAlarmsRequest request,
IServerStreamWriter responseStream,
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Grpc/MxAccessGrpcMapper.cs b/src/ZB.MOM.WW.MxGateway.Server/Grpc/MxAccessGrpcMapper.cs
index 6e7e354..f0070db 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Grpc/MxAccessGrpcMapper.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Grpc/MxAccessGrpcMapper.cs
@@ -23,6 +23,7 @@ public sealed class MxAccessGrpcMapper
/// Maps a gRPC MX command request to a worker command.
///
/// Request payload.
+ /// The mapped worker command.
public WorkerCommand MapCommand(MxCommandRequest request)
{
ArgumentNullException.ThrowIfNull(request);
@@ -39,6 +40,7 @@ public sealed class MxAccessGrpcMapper
/// Maps a worker command reply to a gRPC MX command reply.
///
/// Worker command reply.
+ /// The mapped gRPC command reply.
public MxCommandReply MapCommandReply(WorkerCommandReply reply)
{
ArgumentNullException.ThrowIfNull(reply);
@@ -58,6 +60,7 @@ public sealed class MxAccessGrpcMapper
/// Maps a worker event to a gRPC MX event.
///
/// Worker event to map.
+ /// The mapped gRPC MX event.
public MxEvent MapEvent(WorkerEvent workerEvent)
{
ArgumentNullException.ThrowIfNull(workerEvent);
@@ -73,6 +76,7 @@ public sealed class MxAccessGrpcMapper
/// Creates an OK protocol status.
///
/// Status message.
+ /// A with code .
public static ProtocolStatus Ok(string message = "OK")
{
return new ProtocolStatus
@@ -86,6 +90,7 @@ public sealed class MxAccessGrpcMapper
/// Creates an InvalidRequest protocol status.
///
/// Status message.
+ /// A with code .
public static ProtocolStatus InvalidRequest(string message)
{
return new ProtocolStatus
@@ -99,6 +104,7 @@ public sealed class MxAccessGrpcMapper
/// Creates a SessionNotFound protocol status.
///
/// Status message.
+ /// A with code .
public static ProtocolStatus SessionNotFound(string message)
{
return new ProtocolStatus
@@ -112,6 +118,7 @@ public sealed class MxAccessGrpcMapper
/// Creates a SessionNotReady protocol status.
///
/// Status message.
+ /// A with code .
public static ProtocolStatus SessionNotReady(string message)
{
return new ProtocolStatus
@@ -125,6 +132,7 @@ public sealed class MxAccessGrpcMapper
/// Creates a WorkerUnavailable protocol status.
///
/// Status message.
+ /// A with code .
public static ProtocolStatus WorkerUnavailable(string message)
{
return new ProtocolStatus
@@ -138,6 +146,7 @@ public sealed class MxAccessGrpcMapper
/// Creates a Timeout protocol status.
///
/// Status message.
+ /// A with code .
public static ProtocolStatus Timeout(string message)
{
return new ProtocolStatus
@@ -151,6 +160,7 @@ public sealed class MxAccessGrpcMapper
/// Creates a Canceled protocol status.
///
/// Status message.
+ /// A with code .
public static ProtocolStatus Canceled(string message)
{
return new ProtocolStatus
@@ -164,6 +174,7 @@ public sealed class MxAccessGrpcMapper
/// Creates a ProtocolViolation protocol status.
///
/// Status message.
+ /// A with code .
public static ProtocolStatus ProtocolViolation(string message)
{
return new ProtocolStatus
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Metrics/GatewayMetrics.cs b/src/ZB.MOM.WW.MxGateway.Server/Metrics/GatewayMetrics.cs
index 8727478..9d51983 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Metrics/GatewayMetrics.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Metrics/GatewayMetrics.cs
@@ -380,6 +380,7 @@ public sealed class GatewayMetrics : IDisposable
///
/// Returns a snapshot of all current metric values.
///
+ /// A consistent snapshot of the current metric counters and gauges.
public GatewayMetricsSnapshot GetSnapshot()
{
lock (_syncRoot)
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Security/Audit/CanonicalAuditWriter.cs b/src/ZB.MOM.WW.MxGateway.Server/Security/Audit/CanonicalAuditWriter.cs
index 06a7ad7..b94558f 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Security/Audit/CanonicalAuditWriter.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Security/Audit/CanonicalAuditWriter.cs
@@ -19,7 +19,10 @@ public sealed class CanonicalAuditWriter(
SqliteCanonicalAuditStore store,
ILogger logger) : IAuditWriter
{
- ///
+ /// Persists the audit event to the canonical store; swallows and logs any write failure rather than propagating it.
+ /// The audit event to persist.
+ /// Token to observe for cancellation.
+ /// A task that represents the asynchronous operation.
public async Task WriteAsync(AuditEvent auditEvent, CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(auditEvent);
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Security/Audit/CanonicalForwardingApiKeyAuditStore.cs b/src/ZB.MOM.WW.MxGateway.Server/Security/Audit/CanonicalForwardingApiKeyAuditStore.cs
index befb60b..e947fb0 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Security/Audit/CanonicalForwardingApiKeyAuditStore.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Security/Audit/CanonicalForwardingApiKeyAuditStore.cs
@@ -43,7 +43,10 @@ public sealed class CanonicalForwardingApiKeyAuditStore(
/// The library's keyless schema-init event type.
private const string InitDbEventType = "init-db";
- ///
+ /// Converts the library audit entry to a canonical and forwards it through the gateway's audit writer.
+ /// The API key audit entry to append.
+ /// Token to observe for cancellation.
+ /// A task that represents the asynchronous operation.
public async Task AppendAsync(ApiKeyAuditEntry entry, CancellationToken ct)
{
ArgumentNullException.ThrowIfNull(entry);
@@ -71,7 +74,10 @@ public sealed class CanonicalForwardingApiKeyAuditStore(
await auditWriter.WriteAsync(auditEvent, ct).ConfigureAwait(false);
}
- ///
+ /// Reads recent audit events from the canonical store and maps them back to library-compatible records.
+ /// Maximum number of entries to return.
+ /// Token to observe for cancellation.
+ /// A task that resolves to the most recent audit entries, up to items.
public async Task> ListRecentAsync(int limit, CancellationToken ct)
{
IReadOnlyList events = await store.ListRecentAsync(limit, ct).ConfigureAwait(false);
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Security/Audit/SqliteCanonicalAuditStore.cs b/src/ZB.MOM.WW.MxGateway.Server/Security/Audit/SqliteCanonicalAuditStore.cs
index 64c1133..a617982 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Security/Audit/SqliteCanonicalAuditStore.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Security/Audit/SqliteCanonicalAuditStore.cs
@@ -43,6 +43,7 @@ public sealed class SqliteCanonicalAuditStore(AuthSqliteConnectionFactory connec
/// Inserts a canonical audit event into the audit_event table.
/// The canonical event to persist.
/// Token to observe for cancellation.
+ /// A task that represents the asynchronous operation.
public async Task InsertAsync(AuditEvent auditEvent, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(auditEvent);
@@ -79,6 +80,7 @@ public sealed class SqliteCanonicalAuditStore(AuthSqliteConnectionFactory connec
/// Returns the most recent canonical audit events, newest first.
/// Maximum number of events to return.
/// Token to observe for cancellation.
+ /// A task that resolves to the most recent audit events, up to .
public async Task> ListRecentAsync(int limit, CancellationToken cancellationToken)
{
if (limit <= 0)
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/ApiKeyAdminCliRunner.cs b/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/ApiKeyAdminCliRunner.cs
index 24d01e6..63d4fe2 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/ApiKeyAdminCliRunner.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/ApiKeyAdminCliRunner.cs
@@ -26,6 +26,7 @@ public sealed class ApiKeyAdminCliRunner(ApiKeyAdminCommands commands)
/// API key administration command to execute.
/// Text writer for command output.
/// Token to cancel the asynchronous operation.
+ /// A task that resolves to the exit code (always 0 on success).
public async Task RunAsync(
ApiKeyAdminCommand command,
TextWriter output,
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/ApiKeyAdminParseResult.cs b/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/ApiKeyAdminParseResult.cs
index 412e7b4..a221e21 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/ApiKeyAdminParseResult.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/ApiKeyAdminParseResult.cs
@@ -6,6 +6,7 @@ public sealed record ApiKeyAdminParseResult(
string? Error)
{
/// Returns a result indicating the input was not an API key command.
+ /// A parse result with set to false.
public static ApiKeyAdminParseResult NotApiKeyCommand()
{
return new ApiKeyAdminParseResult(false, null, null);
@@ -13,6 +14,7 @@ public sealed record ApiKeyAdminParseResult(
/// Returns a successful parse result with the parsed API key command.
/// Parsed API key administration command.
+ /// A parse result with set to true and the command populated.
public static ApiKeyAdminParseResult Success(ApiKeyAdminCommand command)
{
return new ApiKeyAdminParseResult(true, command, null);
@@ -20,6 +22,7 @@ public sealed record ApiKeyAdminParseResult(
/// Returns a parse result with the specified error message.
/// Error message describing the parse failure.
+ /// A parse result with set to true and the error message populated.
public static ApiKeyAdminParseResult Fail(string error)
{
return new ApiKeyAdminParseResult(true, null, error);
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/ApiKeyConstraintSerializer.cs b/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/ApiKeyConstraintSerializer.cs
index d2125ba..43ca9d6 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/ApiKeyConstraintSerializer.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Security/Authentication/ApiKeyConstraintSerializer.cs
@@ -12,6 +12,7 @@ public static class ApiKeyConstraintSerializer
/// Serializes API key constraints to JSON, or returns null if the constraints are empty.
/// The constraints to serialize.
+ /// A JSON string representing the constraints, or if empty.
public static string? Serialize(ApiKeyConstraints constraints)
{
ArgumentNullException.ThrowIfNull(constraints);
@@ -20,6 +21,7 @@ public static class ApiKeyConstraintSerializer
/// Deserializes API key constraints from JSON, or returns empty constraints if JSON is null or whitespace.
/// The JSON string to deserialize.
+ /// The deserialized , or when is null or whitespace.
public static ApiKeyConstraints Deserialize(string? json)
{
if (string.IsNullOrWhiteSpace(json))
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/ConstraintEnforcer.cs b/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/ConstraintEnforcer.cs
index 5865a5d..c048068 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/ConstraintEnforcer.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/ConstraintEnforcer.cs
@@ -16,10 +16,7 @@ public sealed class ConstraintEnforcer(
IGalaxyHierarchyCache cache,
IAuditWriter auditWriter) : IConstraintEnforcer
{
- /// Checks read constraints on a tag address.
- /// The API key identity to check constraints for.
- /// Tag address to validate.
- /// Token to observe for cancellation.
+ ///
public Task CheckReadTagAsync(
ApiKeyIdentity? identity,
string tagAddress,
@@ -34,12 +31,7 @@ public sealed class ConstraintEnforcer(
return Task.FromResult(CheckReadTarget(constraints, tagAddress));
}
- /// Checks read constraints on a server and item handle.
- /// The API key identity to check constraints for.
- /// The gateway session containing handle registrations.
- /// The MXAccess server handle.
- /// The MXAccess item handle.
- /// Token to observe for cancellation.
+ ///
public Task CheckReadHandleAsync(
ApiKeyIdentity? identity,
GatewaySession session,
@@ -61,12 +53,7 @@ public sealed class ConstraintEnforcer(
return Task.FromResult(CheckReadTarget(constraints, registration.TagAddress));
}
- /// Checks write constraints on a server and item handle.
- /// The API key identity to check constraints for.
- /// The gateway session containing handle registrations.
- /// The MXAccess server handle.
- /// The MXAccess item handle.
- /// Token to observe for cancellation.
+ ///
public Task CheckWriteHandleAsync(
ApiKeyIdentity? identity,
GatewaySession session,
@@ -115,12 +102,7 @@ public sealed class ConstraintEnforcer(
return Task.FromResult(null);
}
- /// Records a constraint denial audit entry.
- /// The API key identity that was denied.
- /// The command type (e.g., read, write).
- /// The target being accessed (tag address or handle).
- /// The constraint failure details.
- /// Token to observe for cancellation.
+ ///
public async Task RecordDenialAsync(
ApiKeyIdentity? identity,
string commandKind,
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/GatewayRequestIdentityAccessor.cs b/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/GatewayRequestIdentityAccessor.cs
index 8727deb..3c64516 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/GatewayRequestIdentityAccessor.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/GatewayRequestIdentityAccessor.cs
@@ -6,12 +6,10 @@ public sealed class GatewayRequestIdentityAccessor : IGatewayRequestIdentityAcce
{
private readonly AsyncLocal currentIdentity = new();
- /// Gets the current request identity.
+ ///
public ApiKeyIdentity? Current => currentIdentity.Value;
- /// Sets the current identity and returns a scope that restores the previous identity.
- /// The identity to push.
- /// Disposable scope.
+ ///
public IDisposable Push(ApiKeyIdentity identity)
{
ArgumentNullException.ThrowIfNull(identity);
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/GrpcAuthorizationServiceCollectionExtensions.cs b/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/GrpcAuthorizationServiceCollectionExtensions.cs
index f174fc0..2e3c044 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/GrpcAuthorizationServiceCollectionExtensions.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/GrpcAuthorizationServiceCollectionExtensions.cs
@@ -13,6 +13,7 @@ public static class GrpcAuthorizationServiceCollectionExtensions
/// Registers gRPC authorization middleware and scope resolver.
///
/// Service collection to register dependencies into.
+ /// The same for fluent chaining.
public static IServiceCollection AddGatewayGrpcAuthorization(this IServiceCollection services)
{
services.AddSingleton();
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/IConstraintEnforcer.cs b/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/IConstraintEnforcer.cs
index 91d6891..4fae6f8 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/IConstraintEnforcer.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/IConstraintEnforcer.cs
@@ -9,6 +9,7 @@ public interface IConstraintEnforcer
/// The API key identity.
/// Tag address to check.
/// Token to observe for cancellation.
+ /// A task that resolves to the constraint failure, or null if the check passes.
Task CheckReadTagAsync(
ApiKeyIdentity? identity,
string tagAddress,
@@ -20,6 +21,7 @@ public interface IConstraintEnforcer
/// The MXAccess server handle.
/// The MXAccess item handle.
/// Token to observe for cancellation.
+ /// A task that resolves to the constraint failure, or null if the check passes.
Task CheckReadHandleAsync(
ApiKeyIdentity? identity,
GatewaySession session,
@@ -33,6 +35,7 @@ public interface IConstraintEnforcer
/// The MXAccess server handle.
/// The MXAccess item handle.
/// Token to observe for cancellation.
+ /// A task that resolves to the constraint failure, or null if the check passes.
Task CheckWriteHandleAsync(
ApiKeyIdentity? identity,
GatewaySession session,
@@ -46,6 +49,7 @@ public interface IConstraintEnforcer
/// The target of the denied command.
/// The constraint failure details.
/// Token to observe for cancellation.
+ /// A task that represents the asynchronous operation.
Task RecordDenialAsync(
ApiKeyIdentity? identity,
string commandKind,
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/IGatewayRequestIdentityAccessor.cs b/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/IGatewayRequestIdentityAccessor.cs
index c6fe5f0..e38fcef 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/IGatewayRequestIdentityAccessor.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Security/Authorization/IGatewayRequestIdentityAccessor.cs
@@ -10,5 +10,6 @@ public interface IGatewayRequestIdentityAccessor
/// Temporarily pushes an identity onto the scope stack, returning a handle to restore the previous state.
/// API key identity to push.
+ /// A disposable scope that restores the previous identity when disposed.
IDisposable Push(ApiKeyIdentity identity);
}
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Security/Tls/KestrelTlsInspector.cs b/src/ZB.MOM.WW.MxGateway.Server/Security/Tls/KestrelTlsInspector.cs
index 3c80573..770e7e3 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Security/Tls/KestrelTlsInspector.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Security/Tls/KestrelTlsInspector.cs
@@ -16,6 +16,8 @@ public static class KestrelTlsInspector
/// Certificate:Thumbprint), meaning the gateway must supply a
/// generated fallback certificate.
///
+ /// Application configuration containing the Kestrel endpoint settings.
+ /// if a generated certificate is required; otherwise .
public static bool RequiresGeneratedCertificate(IConfiguration configuration)
{
// A Kestrel default certificate applies to every endpoint that lacks its own.
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Security/Tls/SelfSignedCertificateProvider.cs b/src/ZB.MOM.WW.MxGateway.Server/Security/Tls/SelfSignedCertificateProvider.cs
index 17b33cb..7ed10bc 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Security/Tls/SelfSignedCertificateProvider.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Security/Tls/SelfSignedCertificateProvider.cs
@@ -20,6 +20,10 @@ public sealed class SelfSignedCertificateProvider
private readonly ILogger _logger;
private readonly TimeProvider _timeProvider;
+ /// Initializes a new instance of the class.
+ /// TLS configuration options controlling certificate subject, validity, and storage.
+ /// Logger for certificate lifecycle events.
+ /// Time provider used to compute certificate validity windows.
public SelfSignedCertificateProvider(
TlsOptions options,
ILogger logger,
@@ -31,6 +35,7 @@ public sealed class SelfSignedCertificateProvider
}
/// Creates a fresh in-memory ECDSA P-256 self-signed certificate.
+ /// A new self-signed with the configured SANs and validity period.
public X509Certificate2 GenerateCertificate()
{
using ECDsa key = ECDsa.Create(ECCurve.NamedCurves.nistP256);
@@ -89,6 +94,7 @@ public sealed class SelfSignedCertificateProvider
/// Loads the persisted certificate, regenerating when missing,
/// expired (and allowed), or unreadable.
+ /// The loaded or newly generated .
public X509Certificate2 LoadOrCreate()
{
string path = _options.SelfSignedCertPath;
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Sessions/GatewaySession.cs b/src/ZB.MOM.WW.MxGateway.Server/Sessions/GatewaySession.cs
index eebfb4e..99916da 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Sessions/GatewaySession.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Sessions/GatewaySession.cs
@@ -370,6 +370,7 @@ public sealed class GatewaySession
/// Determines whether the session lease has expired.
///
/// Current timestamp for comparison.
+ /// true if the lease has expired; otherwise false.
public bool IsLeaseExpired(DateTimeOffset now)
{
lock (_syncRoot)
@@ -384,6 +385,7 @@ public sealed class GatewaySession
/// Attaches an event subscriber and returns a disposable lease.
///
/// If true, allows multiple concurrent event subscribers.
+ /// A disposable that releases the subscriber slot when disposed.
public IDisposable AttachEventSubscriber(bool allowMultipleSubscribers)
{
lock (_syncRoot)
@@ -412,6 +414,7 @@ public sealed class GatewaySession
///
/// Worker command to invoke.
/// Token to cancel the asynchronous operation.
+ /// A task that resolves to the worker command reply.
public async Task InvokeAsync(
WorkerCommand command,
CancellationToken cancellationToken)
@@ -426,6 +429,7 @@ public sealed class GatewaySession
/// The MXAccess server handle.
/// The MXAccess item handle.
/// The item registration if found.
+ /// true if the item registration was found; otherwise false.
public bool TryGetItemRegistration(
int serverHandle,
int itemHandle,
@@ -487,6 +491,7 @@ public sealed class GatewaySession
/// Server handle returned by the worker.
/// Tag addresses to add.
/// Token to cancel the asynchronous operation.
+ /// A task that resolves to the per-item subscribe results.
public Task> AddItemBulkAsync(
int serverHandle,
IReadOnlyList tagAddresses,
@@ -512,6 +517,7 @@ public sealed class GatewaySession
/// Server handle returned by the worker.
/// Item handles to advise.
/// Token to cancel the asynchronous operation.
+ /// A task that resolves to the per-item subscribe results.
public Task> AdviseItemBulkAsync(
int serverHandle,
IReadOnlyList itemHandles,
@@ -537,6 +543,7 @@ public sealed class GatewaySession
/// Server handle returned by the worker.
/// Item handles to remove.
/// Token to cancel the asynchronous operation.
+ /// A task that resolves to the per-item subscribe results.
public Task> RemoveItemBulkAsync(
int serverHandle,
IReadOnlyList itemHandles,
@@ -562,6 +569,7 @@ public sealed class GatewaySession
/// Server handle returned by the worker.
/// Item handles to un-advise.
/// Token to cancel the asynchronous operation.
+ /// A task that resolves to the per-item subscribe results.
public Task> UnAdviseItemBulkAsync(
int serverHandle,
IReadOnlyList itemHandles,
@@ -587,6 +595,7 @@ public sealed class GatewaySession
/// Server handle returned by the worker.
/// Tag addresses to subscribe to.
/// Token to cancel the asynchronous operation.
+ /// A task that resolves to the per-item subscribe results.
public Task> SubscribeBulkAsync(
int serverHandle,
IReadOnlyList tagAddresses,
@@ -612,6 +621,7 @@ public sealed class GatewaySession
/// Server handle returned by the worker.
/// Item handles to unsubscribe from.
/// Token to cancel the asynchronous operation.
+ /// A task that resolves to the per-item subscribe results.
public Task> UnsubscribeBulkAsync(
int serverHandle,
IReadOnlyList itemHandles,
@@ -635,6 +645,7 @@ public sealed class GatewaySession
/// Server handle returned by the worker.
/// Write entries to execute.
/// Token to cancel the asynchronous operation.
+ /// A task that resolves to the per-item write results.
public Task> WriteBulkAsync(
int serverHandle,
IReadOnlyList entries,
@@ -658,6 +669,7 @@ public sealed class GatewaySession
/// Server handle returned by the worker.
/// Write entries to execute.
/// Token to cancel the asynchronous operation.
+ /// A task that resolves to the per-item write results.
public Task> Write2BulkAsync(
int serverHandle,
IReadOnlyList entries,
@@ -681,6 +693,7 @@ public sealed class GatewaySession
/// Server handle returned by the worker.
/// Write entries to execute.
/// Token to cancel the asynchronous operation.
+ /// A task that resolves to the per-item write results.
public Task> WriteSecuredBulkAsync(
int serverHandle,
IReadOnlyList entries,
@@ -704,6 +717,7 @@ public sealed class GatewaySession
/// Server handle returned by the worker.
/// Write entries to execute.
/// Token to cancel the asynchronous operation.
+ /// A task that resolves to the per-item write results.
public Task> WriteSecured2BulkAsync(
int serverHandle,
IReadOnlyList entries,
@@ -731,6 +745,7 @@ public sealed class GatewaySession
/// Tag addresses to read.
/// Timeout for the read operation.
/// Token to cancel the asynchronous operation.
+ /// A task that resolves to the per-item read results.
public Task> ReadBulkAsync(
int serverHandle,
IReadOnlyList tagAddresses,
@@ -759,6 +774,7 @@ public sealed class GatewaySession
/// Reads events from the worker as an asynchronous enumerable stream.
///
/// Token to cancel the asynchronous operation.
+ /// An async enumerable of worker events.
public IAsyncEnumerable ReadEventsAsync(CancellationToken cancellationToken)
{
IWorkerClient workerClient = GetReadyWorkerClient();
@@ -772,6 +788,7 @@ public sealed class GatewaySession
///
/// Reason for closing the session.
/// Token to cancel the asynchronous operation.
+ /// A task that resolves to the session close result.
///
/// Concurrent close attempts are serialized by _closeLock so only one close
/// runs at a time, but every read/write of _state still passes through
@@ -919,6 +936,7 @@ public sealed class GatewaySession
///
/// Disposes the session and frees associated resources.
///
+ /// A task that represents the asynchronous operation.
///
/// Acquires _closeLock once before disposing so an in-flight
/// finishes before the semaphore is released and
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Sessions/ISessionManager.cs b/src/ZB.MOM.WW.MxGateway.Server/Sessions/ISessionManager.cs
index 2d84f26..87fff00 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Sessions/ISessionManager.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Sessions/ISessionManager.cs
@@ -72,5 +72,6 @@ public interface ISessionManager
/// Shuts down all sessions and the session manager.
/// Token to cancel the asynchronous operation.
+ /// A task that represents the asynchronous operation.
Task ShutdownAsync(CancellationToken cancellationToken);
}
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionManager.cs b/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionManager.cs
index e7a07bf..f140102 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionManager.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionManager.cs
@@ -53,13 +53,7 @@ public sealed class SessionManager : ISessionManager
_sessionSlots = new SemaphoreSlim(_options.Sessions.MaxSessions, _options.Sessions.MaxSessions);
}
- ///
- /// Opens a new gateway session and connects to the worker.
- ///
- /// Session open request.
- /// Client authentication identity.
- /// Cancellation token.
- /// Opened gateway session.
+ ///
public async Task OpenSessionAsync(
SessionOpenRequest request,
string? clientIdentity,
@@ -123,12 +117,7 @@ public sealed class SessionManager : ISessionManager
}
}
- ///
- /// Attempts to retrieve a session by ID.
- ///
- /// Session identifier.
- /// The session if found.
- /// True if session found; otherwise false.
+ ///
public bool TryGetSession(
string sessionId,
[MaybeNullWhen(false)] out GatewaySession session)
@@ -136,13 +125,7 @@ public sealed class SessionManager : ISessionManager
return _registry.TryGet(sessionId, out session);
}
- ///
- /// Invokes a worker command on a session asynchronously.
- ///
- /// Session identifier.
- /// Worker command.
- /// Cancellation token.
- /// Command reply.
+ ///
public async Task InvokeAsync(
string sessionId,
WorkerCommand command,
@@ -169,12 +152,7 @@ public sealed class SessionManager : ISessionManager
}
}
- ///
- /// Reads events from a session's event stream asynchronously.
- ///
- /// Session identifier.
- /// Cancellation token.
- /// Async enumerable of worker events.
+ ///
public IAsyncEnumerable ReadEventsAsync(
string sessionId,
CancellationToken cancellationToken)
@@ -184,12 +162,7 @@ public sealed class SessionManager : ISessionManager
return session.ReadEventsAsync(cancellationToken);
}
- ///
- /// Closes a gateway session asynchronously.
- ///
- /// Session identifier.
- /// Cancellation token.
- /// Session close result.
+ ///
public async Task CloseSessionAsync(
string sessionId,
CancellationToken cancellationToken)
@@ -203,16 +176,7 @@ public sealed class SessionManager : ISessionManager
return result;
}
- ///
- /// Forcefully terminates a session's worker without attempting graceful shutdown.
- /// Mirrors the registry/metrics cleanup that
- /// performs after a successful close, but skips the WorkerClient.ShutdownAsync
- /// step that would otherwise attempt.
- ///
- /// Session identifier.
- /// Reason recorded for the kill.
- /// Cancellation token.
- /// Session close result.
+ ///
public async Task KillWorkerAsync(
string sessionId,
string reason,
@@ -263,12 +227,7 @@ public sealed class SessionManager : ISessionManager
return new SessionCloseResult(sessionId, SessionState.Closed, AlreadyClosed: wasClosed);
}
- ///
- /// Closes all sessions with expired leases asynchronously.
- ///
- /// Current time for lease expiration check.
- /// Cancellation token.
- /// Count of sessions closed.
+ ///
public async Task CloseExpiredLeasesAsync(
DateTimeOffset now,
CancellationToken cancellationToken)
@@ -288,11 +247,7 @@ public sealed class SessionManager : ISessionManager
return closedCount;
}
- ///
- /// Shuts down all active sessions gracefully asynchronously.
- ///
- /// Cancellation token.
- /// Completed task.
+ ///
public async Task ShutdownAsync(CancellationToken cancellationToken)
{
foreach (GatewaySession session in _registry.Snapshot())
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionOpenRequest.cs b/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionOpenRequest.cs
index c48eacf..d60ffe8 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionOpenRequest.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionOpenRequest.cs
@@ -11,6 +11,7 @@ public sealed record SessionOpenRequest(
{
/// Creates a SessionOpenRequest from a gRPC OpenSessionRequest contract.
/// Request payload.
+ /// A new populated from the contract fields.
public static SessionOpenRequest FromContract(OpenSessionRequest request)
{
ArgumentNullException.ThrowIfNull(request);
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionRegistry.cs b/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionRegistry.cs
index ce145cc..e687a06 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionRegistry.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionRegistry.cs
@@ -11,20 +11,13 @@ public sealed class SessionRegistry : ISessionRegistry
{
private readonly ConcurrentDictionary _sessions = new(StringComparer.Ordinal);
- ///
- /// Gets the total count of sessions in the registry.
- ///
+ ///
public int Count => _sessions.Count;
- ///
- /// Gets the count of non-closed sessions.
- ///
+ ///
public int ActiveCount => _sessions.Values.Count(session => session.State is not SessionState.Closed);
- ///
- /// Adds a session to the registry.
- ///
- /// Gateway session to add.
+ ///
public bool TryAdd(GatewaySession session)
{
ArgumentNullException.ThrowIfNull(session);
@@ -32,11 +25,7 @@ public sealed class SessionRegistry : ISessionRegistry
return _sessions.TryAdd(session.SessionId, session);
}
- ///
- /// Retrieves a session by identifier.
- ///
- /// Identifier of the session.
- /// The retrieved session if found.
+ ///
public bool TryGet(
string sessionId,
[MaybeNullWhen(false)] out GatewaySession session)
@@ -44,11 +33,7 @@ public sealed class SessionRegistry : ISessionRegistry
return _sessions.TryGetValue(sessionId, out session);
}
- ///
- /// Removes a session from the registry by identifier.
- ///
- /// Identifier of the session.
- /// The removed session if found.
+ ///
public bool TryRemove(
string sessionId,
[MaybeNullWhen(false)] out GatewaySession session)
@@ -56,9 +41,7 @@ public sealed class SessionRegistry : ISessionRegistry
return _sessions.TryRemove(sessionId, out session);
}
- ///
- /// Returns a snapshot of all sessions in the registry.
- ///
+ ///
public IReadOnlyCollection Snapshot()
{
return _sessions.Values.ToArray();
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionShutdownHostedService.cs b/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionShutdownHostedService.cs
index 426fa29..f403121 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionShutdownHostedService.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionShutdownHostedService.cs
@@ -8,13 +8,17 @@ public sealed class SessionShutdownHostedService(
ISessionManager sessionManager,
ILogger logger) : IHostedService
{
- ///
+ /// No-op start handler; this service only acts on shutdown.
+ /// Cancellation token (unused).
+ /// A completed task.
public Task StartAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
- ///
+ /// Shuts down all active gateway sessions gracefully.
+ /// Token signaled when the host shutdown deadline is reached.
+ /// A task that represents the asynchronous shutdown operation.
public async Task StopAsync(CancellationToken cancellationToken)
{
try
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionWorkerClientFactory.cs b/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionWorkerClientFactory.cs
index eb95139..4a14f6b 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionWorkerClientFactory.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Sessions/SessionWorkerClientFactory.cs
@@ -39,10 +39,7 @@ public sealed class SessionWorkerClientFactory : ISessionWorkerClientFactory
_options = options.Value;
}
- /// Creates a worker client and launches the worker process.
- /// The gateway session.
- /// Cancellation token.
- /// The created worker client.
+ ///
public async Task CreateAsync(
GatewaySession session,
CancellationToken cancellationToken)
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Workers/IWorkerClient.cs b/src/ZB.MOM.WW.MxGateway.Server/Workers/IWorkerClient.cs
index abad654..33d8fdd 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Workers/IWorkerClient.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Workers/IWorkerClient.cs
@@ -19,12 +19,14 @@ public interface IWorkerClient : IAsyncDisposable
/// Initiates the handshake and enters ready state.
/// Token to cancel the asynchronous operation.
+ /// A task that represents the asynchronous operation.
Task StartAsync(CancellationToken cancellationToken);
/// Sends a command to the worker and waits for a reply.
/// Worker command to invoke.
/// Timeout for waiting for the reply.
/// Token to cancel the asynchronous operation.
+ /// A task that resolves to the worker command reply.
Task InvokeAsync(
WorkerCommand command,
TimeSpan timeout,
@@ -32,11 +34,13 @@ public interface IWorkerClient : IAsyncDisposable
/// Reads events from the worker as they arrive.
/// Token to cancel the asynchronous operation.
+ /// An async sequence of worker events.
IAsyncEnumerable ReadEventsAsync(CancellationToken cancellationToken);
/// Gracefully shuts down the worker by closing the connection.
/// Timeout for shutdown.
/// Token to cancel the asynchronous operation.
+ /// A task that represents the asynchronous operation.
Task ShutdownAsync(TimeSpan timeout, CancellationToken cancellationToken);
/// Terminates the worker process immediately with a diagnostic reason.
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Workers/IWorkerProcess.cs b/src/ZB.MOM.WW.MxGateway.Server/Workers/IWorkerProcess.cs
index 0249509..b4e85a2 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Workers/IWorkerProcess.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Workers/IWorkerProcess.cs
@@ -24,6 +24,7 @@ public interface IWorkerProcess : IDisposable
/// Waits for the process to exit with the specified cancellation token.
///
/// Token to cancel the asynchronous operation.
+ /// A value task that completes when the process exits.
ValueTask WaitForExitAsync(CancellationToken cancellationToken);
///
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Workers/OrphanWorkerCleanupHostedService.cs b/src/ZB.MOM.WW.MxGateway.Server/Workers/OrphanWorkerCleanupHostedService.cs
index efa4a49..5d05c6d 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Workers/OrphanWorkerCleanupHostedService.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Workers/OrphanWorkerCleanupHostedService.cs
@@ -8,7 +8,9 @@ public sealed class OrphanWorkerCleanupHostedService(
OrphanWorkerTerminator terminator,
ILogger logger) : IHostedService
{
- ///
+ /// Terminates any orphaned MXAccess worker processes found at startup.
+ /// Token to observe for cancellation (unused; cleanup is best-effort).
+ /// A completed task.
public Task StartAsync(CancellationToken cancellationToken)
{
try
@@ -25,6 +27,8 @@ public sealed class OrphanWorkerCleanupHostedService(
return Task.CompletedTask;
}
- ///
+ /// Performs no action on stop; all cleanup runs at startup.
+ /// Token to observe for cancellation (unused).
+ /// A completed task.
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Workers/SystemWorkerProcess.cs b/src/ZB.MOM.WW.MxGateway.Server/Workers/SystemWorkerProcess.cs
index ac86232..698ef12 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Workers/SystemWorkerProcess.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Workers/SystemWorkerProcess.cs
@@ -28,7 +28,7 @@ internal sealed class SystemWorkerProcess(Process process) : IWorkerProcess
process.Kill(entireProcessTree);
}
- ///
+ /// Releases the underlying process resources.
public void Dispose()
{
process.Dispose();
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerClient.cs b/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerClient.cs
index 3761ddb..54ab22f 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerClient.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerClient.cs
@@ -78,10 +78,10 @@ public sealed class WorkerClient : IWorkerClient
_lastHeartbeatAt = _timeProvider.GetUtcNow();
}
- /// Gets the worker's session ID.
+ ///
public string SessionId => _connection.SessionId;
- /// Gets the worker process ID.
+ ///
public int? ProcessId
{
get
@@ -93,7 +93,7 @@ public sealed class WorkerClient : IWorkerClient
}
}
- /// Gets the current client state.
+ ///
public WorkerClientState State
{
get
@@ -105,7 +105,7 @@ public sealed class WorkerClient : IWorkerClient
}
}
- /// Gets the timestamp of the last received heartbeat.
+ ///
public DateTimeOffset LastHeartbeatAt
{
get
@@ -117,8 +117,7 @@ public sealed class WorkerClient : IWorkerClient
}
}
- /// Starts the worker client and completes the handshake.
- /// Cancellation token.
+ ///
public async Task StartAsync(CancellationToken cancellationToken)
{
ThrowIfDisposed();
@@ -141,11 +140,7 @@ public sealed class WorkerClient : IWorkerClient
_heartbeatLoopTask = Task.Run(HeartbeatLoopAsync);
}
- /// Invokes a command on the worker and waits for reply.
- /// The command to invoke.
- /// Command timeout.
- /// Cancellation token.
- /// The command reply.
+ ///
public async Task InvokeAsync(
WorkerCommand command,
TimeSpan timeout,
@@ -228,9 +223,7 @@ public sealed class WorkerClient : IWorkerClient
}
}
- /// Reads events from the worker as an async stream.
- /// Cancellation token.
- /// Async enumerable of worker events.
+ ///
public async IAsyncEnumerable ReadEventsAsync(
[EnumeratorCancellation] CancellationToken cancellationToken)
{
@@ -242,9 +235,7 @@ public sealed class WorkerClient : IWorkerClient
}
}
- /// Shuts down the worker gracefully.
- /// Shutdown timeout.
- /// Cancellation token.
+ ///
public async Task ShutdownAsync(TimeSpan timeout, CancellationToken cancellationToken)
{
ThrowIfDisposed();
@@ -289,8 +280,7 @@ public sealed class WorkerClient : IWorkerClient
}
}
- /// Terminates the worker process immediately.
- /// Reason for termination.
+ ///
public void Kill(string reason)
{
ThrowIfDisposed();
@@ -302,6 +292,7 @@ public sealed class WorkerClient : IWorkerClient
}
/// Disposes the worker client and releases resources.
+ /// A task that represents the asynchronous dispose operation.
public async ValueTask DisposeAsync()
{
if (_disposed)
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerFrameWriter.cs b/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerFrameWriter.cs
index 999fab5..0e8bfe1 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerFrameWriter.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerFrameWriter.cs
@@ -30,6 +30,7 @@ public sealed class WorkerFrameWriter
///
/// Worker envelope message to write.
/// Token to cancel the asynchronous operation.
+ /// A value task that represents the asynchronous operation.
public async ValueTask WriteAsync(
WorkerEnvelope envelope,
CancellationToken cancellationToken = default)
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerProcessHandle.cs b/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerProcessHandle.cs
index 0ffb814..619bfd8 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerProcessHandle.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerProcessHandle.cs
@@ -30,7 +30,7 @@ public sealed class WorkerProcessHandle : IDisposable
/// Gets the time when the process was launched.
public DateTimeOffset LaunchedAt { get; }
- ///
+ /// Releases the underlying worker process resources.
public void Dispose()
{
Process.Dispose();
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerProcessLauncher.cs b/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerProcessLauncher.cs
index c8a6ab7..cab6fe1 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerProcessLauncher.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerProcessLauncher.cs
@@ -58,12 +58,7 @@ public sealed class WorkerProcessLauncher : IWorkerProcessLauncher
_logger = logger ?? NullLogger.Instance;
}
- ///
- /// Launches a worker process and waits for startup.
- ///
- /// Request payload.
- /// Token to cancel the asynchronous operation.
- /// Handle to the launched worker process.
+ ///
public async Task LaunchAsync(
WorkerProcessLaunchRequest request,
CancellationToken cancellationToken = default)
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerProcessStartedProbe.cs b/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerProcessStartedProbe.cs
index 1e19a98..b9caedd 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerProcessStartedProbe.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerProcessStartedProbe.cs
@@ -2,11 +2,7 @@ namespace ZB.MOM.WW.MxGateway.Server.Workers;
public sealed class WorkerProcessStartedProbe : IWorkerStartupProbe
{
- /// Verifies that the worker process has started and has not exited.
- /// Worker process to verify.
- /// Process launch request.
- /// Token to cancel the asynchronous operation.
- /// Completed task if process is running.
+ ///
public Task WaitUntilReadyAsync(
IWorkerProcess process,
WorkerProcessLaunchRequest request,
diff --git a/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerServiceCollectionExtensions.cs b/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerServiceCollectionExtensions.cs
index d15e914..7beb761 100644
--- a/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerServiceCollectionExtensions.cs
+++ b/src/ZB.MOM.WW.MxGateway.Server/Workers/WorkerServiceCollectionExtensions.cs
@@ -5,6 +5,7 @@ public static class WorkerServiceCollectionExtensions
{
/// Registers worker process launcher and factory services.
/// Service collection to register services.
+ /// The same to allow chaining.
public static IServiceCollection AddWorkerProcessLauncher(this IServiceCollection services)
{
services.AddSingleton();
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Configuration/GatewayOptionsValidatorTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Configuration/GatewayOptionsValidatorTests.cs
index 49d8165..dff83bb 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Configuration/GatewayOptionsValidatorTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Configuration/GatewayOptionsValidatorTests.cs
@@ -46,6 +46,7 @@ public sealed class GatewayOptionsValidatorTests
Tls = tls,
};
+ /// Verifies that the validator succeeds when TLS options are left at their defaults.
[Fact]
public void Validate_Succeeds_WithDefaultTlsOptions()
{
@@ -53,6 +54,7 @@ public sealed class GatewayOptionsValidatorTests
Assert.True(result.Succeeded);
}
+ /// Verifies that the validator fails when TLS validity years is set to zero.
[Fact]
public void Validate_Fails_WhenTlsValidityYearsOutOfRange()
{
@@ -62,6 +64,7 @@ public sealed class GatewayOptionsValidatorTests
Assert.Contains(result.Failures!, f => f.Contains("MxGateway:Tls:ValidityYears"));
}
+ /// Verifies that the validator fails when TLS validity years exceeds the allowed maximum.
[Fact]
public void Validate_Fails_WhenTlsValidityYearsTooLarge()
{
@@ -71,6 +74,7 @@ public sealed class GatewayOptionsValidatorTests
Assert.Contains(result.Failures!, f => f.Contains("MxGateway:Tls:ValidityYears"));
}
+ /// Verifies that the validator fails when an additional DNS name is blank or whitespace.
[Fact]
public void Validate_Fails_WhenAdditionalDnsNameBlank()
{
@@ -80,6 +84,7 @@ public sealed class GatewayOptionsValidatorTests
Assert.Contains(result.Failures!, f => f.Contains("MxGateway:Tls:AdditionalDnsNames"));
}
+ /// Verifies that the validator fails when the self-signed certificate path is blank.
[Fact]
public void Validate_Fails_WhenSelfSignedCertPathBlank()
{
@@ -89,6 +94,7 @@ public sealed class GatewayOptionsValidatorTests
Assert.Contains(result.Failures!, f => f.Contains("MxGateway:Tls:SelfSignedCertPath must not be blank."));
}
+ /// Verifies that the validator fails when LDAP is enabled with port zero.
[Fact]
public void Validate_Fails_WhenLdapPortIsZero()
{
@@ -100,6 +106,7 @@ public sealed class GatewayOptionsValidatorTests
f => f.Contains("MxGateway:Ldap:Port must be between 1 and 65535 (was 0)"));
}
+ /// Verifies that the validator fails when LDAP is enabled with a port number above 65535.
[Fact]
public void Validate_Fails_WhenLdapPortExceedsMaximum()
{
@@ -111,6 +118,7 @@ public sealed class GatewayOptionsValidatorTests
f => f.Contains("MxGateway:Ldap:Port must be between 1 and 65535 (was 70000)"));
}
+ /// Verifies that the validator succeeds when LDAP is enabled with a valid port in range.
[Fact]
public void Validate_Succeeds_WhenLdapEnabledWithValidPort()
{
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Configuration/TlsOptionsBindingTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Configuration/TlsOptionsBindingTests.cs
index 796a4ca..599a8ec 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Configuration/TlsOptionsBindingTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Configuration/TlsOptionsBindingTests.cs
@@ -6,6 +6,7 @@ namespace ZB.MOM.WW.MxGateway.Tests.Configuration;
public sealed class TlsOptionsBindingTests
{
+ /// Verifies that TLS option defaults are applied when the configuration section is absent.
[Fact]
public void Defaults_AreApplied_WhenSectionAbsent()
{
@@ -16,6 +17,7 @@ public sealed class TlsOptionsBindingTests
Assert.False(string.IsNullOrWhiteSpace(options.SelfSignedCertPath));
}
+ /// Verifies that TLS options bind correctly from the MxGateway:Tls configuration section.
[Fact]
public void Binds_FromMxGatewayTlsSection()
{
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Dashboard/DashboardBrowseServiceTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Dashboard/DashboardBrowseServiceTests.cs
index d749e08..96962c3 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Dashboard/DashboardBrowseServiceTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Dashboard/DashboardBrowseServiceTests.cs
@@ -144,7 +144,7 @@ public sealed class DashboardBrowseServiceTests
private sealed class StubGalaxyHierarchyCache(GalaxyHierarchyCacheEntry initial) : IGalaxyHierarchyCache
{
- /// Mutable so a single test can swap the entry mid-flight.
+ ///
public GalaxyHierarchyCacheEntry Current { get; set; } = initial;
///
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Diagnostics/AuthStoreHealthCheckTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Diagnostics/AuthStoreHealthCheckTests.cs
index df87ed3..377c67d 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Diagnostics/AuthStoreHealthCheckTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Diagnostics/AuthStoreHealthCheckTests.cs
@@ -12,6 +12,8 @@ public sealed class AuthStoreHealthCheckTests
return new AuthSqliteConnectionFactory(sqlitePath);
}
+ /// Verifies that the health check reports Healthy when the auth store is reachable.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Healthy_WhenStoreReachable()
{
@@ -25,6 +27,8 @@ public sealed class AuthStoreHealthCheckTests
finally { if (File.Exists(path)) File.Delete(path); }
}
+ /// Verifies that the health check reports Unhealthy when the store path cannot be opened.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Unhealthy_WhenPathUnusable()
{
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Diagnostics/GatewayLogRedactorSeamTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Diagnostics/GatewayLogRedactorSeamTests.cs
index 494808e..abcbeaa 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Diagnostics/GatewayLogRedactorSeamTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Diagnostics/GatewayLogRedactorSeamTests.cs
@@ -4,6 +4,7 @@ using Xunit;
public class GatewayLogRedactorSeamTests
{
+ /// Verifies that the log redactor masks the API key secret in the ClientIdentity field.
[Fact]
public void Redact_MasksApiKeyInClientIdentity()
{
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Galaxy/GalaxyBrowseProjectorTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Galaxy/GalaxyBrowseProjectorTests.cs
index 50a7d62..0eb860f 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Galaxy/GalaxyBrowseProjectorTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Galaxy/GalaxyBrowseProjectorTests.cs
@@ -229,6 +229,7 @@ public sealed class GalaxyBrowseProjectorTests
/// HasMatchingDescendant, the depth-first walk would loop forever; the
/// 5-second xUnit timeout asserts termination.
///
+ /// A task that represents the asynchronous operation.
[Fact(Timeout = 5000)]
public async Task Project_CyclicDescendants_DoesNotInfiniteLoop()
{
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Galaxy/GalaxyDeployNotifierTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Galaxy/GalaxyDeployNotifierTests.cs
index 3324efa..a5caa80 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Galaxy/GalaxyDeployNotifierTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Galaxy/GalaxyDeployNotifierTests.cs
@@ -5,6 +5,7 @@ namespace ZB.MOM.WW.MxGateway.Tests.Galaxy;
public sealed class GalaxyDeployNotifierTests
{
/// Verifies that a subscriber blocks until a deploy event is published.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SubscribeAsync_NoLatestEvent_BlocksUntilPublish()
{
@@ -34,6 +35,7 @@ public sealed class GalaxyDeployNotifierTests
}
/// Verifies that a subscriber immediately receives a cached latest deploy event.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SubscribeAsync_WithLatestEvent_BootstrapsImmediately()
{
@@ -53,6 +55,7 @@ public sealed class GalaxyDeployNotifierTests
}
/// Verifies that published events fan out to all active subscribers.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Publish_FansOutToAllSubscribers()
{
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Galaxy/GalaxyFilterInputSafetyTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Galaxy/GalaxyFilterInputSafetyTests.cs
index ab18465..766b28f 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Galaxy/GalaxyFilterInputSafetyTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Galaxy/GalaxyFilterInputSafetyTests.cs
@@ -45,6 +45,7 @@ public sealed class GalaxyFilterInputSafetyTests
];
/// Returns adversarial input cases for theory tests.
+ /// Theory data containing adversarial input strings.
public static TheoryData AdversarialInputCases()
{
TheoryData data = [];
@@ -222,6 +223,7 @@ public sealed class GalaxyFilterInputSafetyTests
/// zero matches rather than returning the whole hierarchy or faulting.
///
/// An adversarial glob containing SQL metacharacters or LIKE wildcards.
+ /// A task that represents the asynchronous operation.
[Theory]
[MemberData(nameof(AdversarialInputCases))]
public async Task DiscoverHierarchy_WithAdversarialTagNameGlob_ReturnsZeroMatches(string glob)
@@ -242,6 +244,7 @@ public sealed class GalaxyFilterInputSafetyTests
/// a query fragment or matching unrelated objects.
///
/// An adversarial tag name containing SQL metacharacters or LIKE wildcards.
+ /// A task that represents the asynchronous operation.
[Theory]
[MemberData(nameof(AdversarialInputCases))]
public async Task DiscoverHierarchy_WithAdversarialRootTagName_ReturnsNotFound(string rootTagName)
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Galaxy/GalaxyHierarchyCacheTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Galaxy/GalaxyHierarchyCacheTests.cs
index 96dcb2a..1f9a805 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Galaxy/GalaxyHierarchyCacheTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Galaxy/GalaxyHierarchyCacheTests.cs
@@ -34,6 +34,7 @@ public sealed class GalaxyHierarchyCacheTests : IDisposable
/// connection failure, but it is fully covered by the cache's exception
/// branch and does not require a real TCP probe from a unit test.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RefreshAsync_WhenRepositoryThrows_MarksUnavailableAndDoesNotPublish()
{
@@ -130,6 +131,7 @@ public sealed class GalaxyHierarchyCacheTests : IDisposable
/// Verifies a successful refresh writes the browse dataset to the on-disk
/// snapshot store so a later cold start can restore it.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RefreshAsync_WhenSuccessful_PersistsSnapshotToDisk()
{
@@ -155,6 +157,7 @@ public sealed class GalaxyHierarchyCacheTests : IDisposable
/// snapshot exists on disk, the cache serves that data with Stale status
/// rather than coming up empty.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RefreshAsync_WhenDatabaseUnreachableButSnapshotOnDisk_RestoresStaleData()
{
@@ -185,6 +188,7 @@ public sealed class GalaxyHierarchyCacheTests : IDisposable
/// Galaxy database, the cache promotes the restored data to Healthy
/// without re-running the heavy hierarchy and attribute queries.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RefreshAsync_WhenSnapshotDeployMatchesLive_PromotesToHealthyWithoutHeavyQuery()
{
@@ -216,6 +220,7 @@ public sealed class GalaxyHierarchyCacheTests : IDisposable
/// the full bootstrap budget while the live Galaxy query is still running.
/// Regression test for Server-033.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RefreshAsync_RestoredSnapshotCompletesFirstLoadBeforeLiveQueryReturns()
{
@@ -249,6 +254,7 @@ public sealed class GalaxyHierarchyCacheTests : IDisposable
/// ignores the unreadable file and comes up Unavailable when the database is
/// also unreachable. Regression test for Server-037.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RefreshAsync_WhenSnapshotFileCorrupt_ComesUpUnavailableWithoutThrowing()
{
@@ -271,6 +277,7 @@ public sealed class GalaxyHierarchyCacheTests : IDisposable
/// restore from disk — an unreachable database leaves it Unavailable.
/// Regression test for Server-037.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RefreshAsync_WhenPersistDisabled_DoesNotRestoreFromDisk()
{
@@ -291,6 +298,7 @@ public sealed class GalaxyHierarchyCacheTests : IDisposable
/// (the refresh token is cancelled) is not logged as a persistence failure.
/// Regression test for Server-036.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RefreshAsync_WhenSnapshotSaveCancelledAtShutdown_DoesNotLogPersistFailure()
{
@@ -402,14 +410,25 @@ public sealed class GalaxyHierarchyCacheTests : IDisposable
/// Gets the list of recorded log entries.
public List<(LogLevel Level, string Message)> Entries { get; } = [];
- ///
+ /// Returns a no-op scope.
+ /// The type of state used for the scope.
+ /// The scope state.
+ /// A no-op disposable scope.
public IDisposable BeginScope(TState state)
where TState : notnull => NullScope.Instance;
- ///
+ /// Returns for all log levels.
+ /// The log level to check.
+ /// .
public bool IsEnabled(LogLevel logLevel) => true;
- ///
+ /// Records the log entry.
+ /// The type of the state object.
+ /// The log level.
+ /// The event id.
+ /// The state object.
+ /// The exception, if any.
+ /// Delegate that formats the log message.
public void Log(
LogLevel logLevel,
EventId eventId,
@@ -424,7 +443,7 @@ public sealed class GalaxyHierarchyCacheTests : IDisposable
{
public static readonly NullScope Instance = new();
- ///
+ /// No-op dispose.
public void Dispose()
{
}
@@ -467,7 +486,7 @@ public sealed class GalaxyHierarchyCacheTests : IDisposable
}
}
- ///
+ /// Deletes temporary snapshot files created during the test run.
public void Dispose()
{
foreach (string path in _tempPaths)
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Galaxy/GalaxyHierarchyRefreshServiceTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Galaxy/GalaxyHierarchyRefreshServiceTests.cs
index 7cf5045..a8a0ac9 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Galaxy/GalaxyHierarchyRefreshServiceTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Galaxy/GalaxyHierarchyRefreshServiceTests.cs
@@ -14,6 +14,7 @@ namespace ZB.MOM.WW.MxGateway.Tests.Galaxy;
public sealed class GalaxyHierarchyRefreshServiceTests
{
/// Verifies that the background service does not fault when the first refresh throws a non-cancellation exception.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ExecuteAsync_WhenFirstRefreshThrowsNonCancellationException_DoesNotFaultBackgroundService()
{
@@ -69,11 +70,10 @@ public sealed class GalaxyHierarchyRefreshServiceTests
/// Gets a task that completes once refresh has been invoked at least once.
public Task FirstRefreshAttempted => firstRefreshAttempted.Task;
- /// Gets the current cache entry.
+ ///
public GalaxyHierarchyCacheEntry Current => GalaxyHierarchyCacheEntry.Empty;
- /// Refreshes the cache asynchronously and throws the configured exception.
- /// Token to observe for cancellation.
+ ///
public Task RefreshAsync(CancellationToken cancellationToken)
{
RefreshCallCount++;
@@ -81,8 +81,7 @@ public sealed class GalaxyHierarchyRefreshServiceTests
throw toThrow;
}
- /// Waits for the first load and completes immediately.
- /// Token to observe for cancellation.
+ ///
public Task WaitForFirstLoadAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
}
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Galaxy/GalaxyHierarchySnapshotStoreTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Galaxy/GalaxyHierarchySnapshotStoreTests.cs
index 6da3d34..6cfc03a 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Galaxy/GalaxyHierarchySnapshotStoreTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Galaxy/GalaxyHierarchySnapshotStoreTests.cs
@@ -13,6 +13,7 @@ public sealed class GalaxyHierarchySnapshotStoreTests : IDisposable
private readonly List _tempPaths = [];
/// Verifies that snapshots are correctly saved to and loaded from disk.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SaveAsync_ThenTryLoadAsync_RoundTripsRows()
{
@@ -41,6 +42,7 @@ public sealed class GalaxyHierarchySnapshotStoreTests : IDisposable
}
/// Verifies that loading returns null when no snapshot file exists.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task TryLoadAsync_WhenNoFileExists_ReturnsNull()
{
@@ -50,6 +52,7 @@ public sealed class GalaxyHierarchySnapshotStoreTests : IDisposable
}
/// Verifies that save writes nothing when persistence is disabled.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SaveAsync_WhenPersistenceDisabled_WritesNothing()
{
@@ -63,6 +66,7 @@ public sealed class GalaxyHierarchySnapshotStoreTests : IDisposable
}
/// Verifies that loading returns null when the file contains invalid JSON.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task TryLoadAsync_WhenFileIsCorruptJson_ReturnsNull()
{
@@ -74,6 +78,7 @@ public sealed class GalaxyHierarchySnapshotStoreTests : IDisposable
}
/// Verifies that loading returns null when the schema version is unrecognized.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task TryLoadAsync_WhenSchemaVersionUnrecognized_ReturnsNull()
{
@@ -85,6 +90,7 @@ public sealed class GalaxyHierarchySnapshotStoreTests : IDisposable
}
/// Verifies that saving overwrites an earlier snapshot.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SaveAsync_OverwritesAnEarlierSnapshot()
{
@@ -165,7 +171,7 @@ public sealed class GalaxyHierarchySnapshotStoreTests : IDisposable
return path;
}
- ///
+ /// Deletes all temporary snapshot files created during the test.
public void Dispose()
{
foreach (string path in _tempPaths)
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardApiKeyManagementServiceTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardApiKeyManagementServiceTests.cs
index c27241d..1771951 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardApiKeyManagementServiceTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardApiKeyManagementServiceTests.cs
@@ -29,6 +29,7 @@ public sealed class DashboardApiKeyManagementServiceTests : IDisposable
private readonly List _tempDirectories = [];
/// Verifies that unauthorized users cannot create API keys.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CreateAsync_UnauthorizedUser_DoesNotCreate()
{
@@ -45,6 +46,7 @@ public sealed class DashboardApiKeyManagementServiceTests : IDisposable
}
/// Verifies that authorized users create a verifiable, constrained key and audit it.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CreateAsync_AuthorizedUser_CreatesVerifiableKeyAndAudits()
{
@@ -79,6 +81,7 @@ public sealed class DashboardApiKeyManagementServiceTests : IDisposable
}
/// Verifies that creating a key whose id already exists is rejected.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CreateAsync_DuplicateKeyId_ReportsConflict()
{
@@ -96,6 +99,7 @@ public sealed class DashboardApiKeyManagementServiceTests : IDisposable
}
/// Verifies that authorized users can revoke keys with audit trail.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RevokeAsync_AuthorizedUser_RevokesAndAudits()
{
@@ -121,6 +125,7 @@ public sealed class DashboardApiKeyManagementServiceTests : IDisposable
}
/// Verifies that authorized users can rotate a key's secret with audit trail.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RotateAsync_AuthorizedUser_RotatesAndAudits()
{
@@ -153,6 +158,7 @@ public sealed class DashboardApiKeyManagementServiceTests : IDisposable
}
/// Verifies that authorized users can delete revoked keys with audit trail.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DeleteAsync_AuthorizedUser_DeletesRevokedKeyAndAudits()
{
@@ -181,6 +187,7 @@ public sealed class DashboardApiKeyManagementServiceTests : IDisposable
/// dashboard-delete-key audit entry with Details = "not-found-or-active" is still
/// written — audit completeness for refused deletes.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DeleteAsync_ActiveKey_ReportsFriendlyErrorAndAudits()
{
@@ -206,6 +213,7 @@ public sealed class DashboardApiKeyManagementServiceTests : IDisposable
/// A blank key id fails validation before any store or audit call runs.
/// A blank or whitespace key identifier.
+ /// A task that represents the asynchronous operation.
[Theory]
[InlineData("")]
[InlineData(" ")]
@@ -229,6 +237,7 @@ public sealed class DashboardApiKeyManagementServiceTests : IDisposable
/// non-canonical scope string rather than persisting a key whose scope the authorization
/// resolver never matches.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CreateAsync_UnknownScope_DoesNotCreate()
{
@@ -255,6 +264,7 @@ public sealed class DashboardApiKeyManagementServiceTests : IDisposable
/// Phase 3 canonical audit shape: the dashboard-create-key canonical AuditEvent records
/// the operator username as Actor and the managed keyId as Target.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CreateAsync_AuthorizedUser_CanonicalAuditEventHasOperatorAsActorAndKeyIdAsTarget()
{
@@ -386,7 +396,10 @@ public sealed class DashboardApiKeyManagementServiceTests : IDisposable
/// Gets the recorded canonical audit events.
public List Events { get; } = [];
- ///
+ /// Records the audit event and returns a completed task.
+ /// The audit event to record.
+ /// Cancellation token (unused).
+ /// A task that represents the asynchronous operation.
public Task WriteAsync(ZB.MOM.WW.Audit.AuditEvent auditEvent, CancellationToken cancellationToken = default)
{
Events.Add(auditEvent);
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardAuthenticatorTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardAuthenticatorTests.cs
index 7cd03a6..91caae6 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardAuthenticatorTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardAuthenticatorTests.cs
@@ -20,6 +20,8 @@ namespace ZB.MOM.WW.MxGateway.Tests.Gateway.Dashboard;
public sealed class DashboardAuthenticatorTests
{
/// A blank username is rejected without touching the LDAP provider.
+ /// A null, empty, or whitespace-only username.
+ /// A task that represents the asynchronous operation.
[Theory]
[InlineData(null)]
[InlineData("")]
@@ -40,6 +42,7 @@ public sealed class DashboardAuthenticatorTests
}
/// A blank password is rejected without touching the LDAP provider.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AuthenticateAsync_BlankPassword_FailsWithoutCallingLdap()
{
@@ -60,6 +63,8 @@ public sealed class DashboardAuthenticatorTests
/// A failed LDAP outcome (any failure bucket, including )
/// maps to the generic dashboard failure without leaking the raw password.
///
+ /// The LDAP failure kind to test.
+ /// A task that represents the asynchronous operation.
[Theory]
[InlineData(LdapAuthFailure.Disabled)]
[InlineData(LdapAuthFailure.BadCredentials)]
@@ -87,6 +92,7 @@ public sealed class DashboardAuthenticatorTests
/// name (ClaimTypes.Name), and the username (ClaimTypes.NameIdentifier), under the
/// dashboard authentication scheme.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AuthenticateAsync_Success_BuildsPrincipalWithExpectedClaims()
{
@@ -132,6 +138,7 @@ public sealed class DashboardAuthenticatorTests
/// ZbClaimTypes.DisplayName ("zb:displayname") with the display name — while keeping
/// ClaimTypes.NameIdentifier, ClaimTypes.Name, and mxgateway:ldap_group claims intact.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AuthenticateAsync_Success_EmitsCanonicalZbClaims()
{
@@ -183,6 +190,7 @@ public sealed class DashboardAuthenticatorTests
/// When the user authenticates but none of their groups map to a dashboard role,
/// the login is denied (the long-standing "no roles matched → denied" rule).
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AuthenticateAsync_NoRolesMatched_DeniesLogin()
{
@@ -216,6 +224,7 @@ public sealed class DashboardAuthenticatorTests
/// for the realistic (already-short) group shape.
///
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AuthenticateAsync_GroupAsDistinguishedNameFromService_ResolvesRoleAndSurfacesServiceValue()
{
@@ -243,6 +252,7 @@ public sealed class DashboardAuthenticatorTests
}
/// The (already-trimmed) username from the LDAP result flows onto the principal.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AuthenticateAsync_UsesUsernameFromLdapResult()
{
@@ -296,10 +306,17 @@ public sealed class DashboardAuthenticatorTests
///
private sealed class FakeLdapAuthService(LdapAuthResult result) : ILdapAuthService
{
+ /// Gets a value indicating whether AuthenticateAsync was called.
public bool WasCalled { get; private set; }
+ /// Gets the username passed to the most recent AuthenticateAsync call.
public string? LastUsername { get; private set; }
+ /// Records the call and returns the configured result.
+ /// The username passed by the authenticator.
+ /// The password passed by the authenticator.
+ /// Cancellation token.
+ /// A task that resolves to the configured LDAP authentication result.
public Task AuthenticateAsync(string username, string password, CancellationToken ct)
{
WasCalled = true;
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardAuthorizationHandlerTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardAuthorizationHandlerTests.cs
index 6dbf84a..9d4ab2d 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardAuthorizationHandlerTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardAuthorizationHandlerTests.cs
@@ -11,6 +11,7 @@ namespace ZB.MOM.WW.MxGateway.Tests.Gateway.Dashboard;
public sealed class DashboardAuthorizationHandlerTests
{
/// Verifies that unauthenticated remote requests fail authorization.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task HandleAsync_UnauthenticatedRemoteRequest_DoesNotSucceed()
{
@@ -24,6 +25,7 @@ public sealed class DashboardAuthorizationHandlerTests
}
/// Verifies that anonymous localhost access succeeds when allowed.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task HandleAsync_AnonymousLocalhostAllowed_Succeeds()
{
@@ -40,6 +42,7 @@ public sealed class DashboardAuthorizationHandlerTests
/// Verifies that the anonymous-localhost bypass is denied when AllowAnonymousLocalhost
/// is off, even on a loopback connection — the misconfiguration must not expose the dashboard.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task HandleAsync_AnonymousLocalhostDisallowed_DoesNotSucceed()
{
@@ -56,6 +59,7 @@ public sealed class DashboardAuthorizationHandlerTests
/// Verifies that the anonymous-localhost bypass stays scoped to loopback: an anonymous
/// request from a non-loopback address is denied even when AllowAnonymousLocalhost is on.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task HandleAsync_AnonymousLocalhostAllowedFromRemoteAddress_DoesNotSucceed()
{
@@ -69,6 +73,7 @@ public sealed class DashboardAuthorizationHandlerTests
}
/// Verifies that an authenticated user without any dashboard role fails the viewer requirement.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task HandleAsync_AuthenticatedWithoutDashboardRole_DoesNotSucceed()
{
@@ -82,6 +87,7 @@ public sealed class DashboardAuthorizationHandlerTests
}
/// Verifies that a Viewer satisfies the viewer-or-admin requirement.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task HandleAsync_ViewerRole_SatisfiesViewerPolicy()
{
@@ -95,6 +101,7 @@ public sealed class DashboardAuthorizationHandlerTests
}
/// Verifies that an Admin satisfies the admin-only requirement.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task HandleAsync_AdminRole_SatisfiesAdminPolicy()
{
@@ -108,6 +115,7 @@ public sealed class DashboardAuthorizationHandlerTests
}
/// Verifies that a Viewer does NOT satisfy the admin-only requirement.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task HandleAsync_ViewerRole_DoesNotSatisfyAdminPolicy()
{
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardCookieOptionsTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardCookieOptionsTests.cs
index 95ed26c..557910c 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardCookieOptionsTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardCookieOptionsTests.cs
@@ -11,6 +11,7 @@ namespace ZB.MOM.WW.MxGateway.Tests.Gateway.Dashboard;
public sealed class DashboardCookieOptionsTests
{
/// Verifies that the application configures secure dashboard authentication cookies.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Build_ConfiguresSecureDashboardCookie()
{
@@ -36,6 +37,7 @@ public sealed class DashboardCookieOptionsTests
/// relaxes the cookie to so
/// the dashboard can be reached over plain HTTP in dev.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Build_WithRequireHttpsCookieFalse_UsesSameAsRequest()
{
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardGroupRoleMapperTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardGroupRoleMapperTests.cs
index 935f7c7..57a8240 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardGroupRoleMapperTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardGroupRoleMapperTests.cs
@@ -35,6 +35,7 @@ public sealed class DashboardGroupRoleMapperTests
/// Verifies full-DN match, leading-RDN fallback, case-insensitivity, and unmapped → empty.
/// The LDAP group name or distinguished name.
/// The expected role or null if no match.
+ /// A task that represents the asynchronous operation.
[Theory]
[InlineData("GwAdmin", DashboardRoles.Admin)]
[InlineData("gwadmin", DashboardRoles.Admin)]
@@ -61,6 +62,7 @@ public sealed class DashboardGroupRoleMapperTests
}
/// Verifies that admin and viewer roles are both emitted when both groups are present.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task MapAsync_AdminPlusViewer_BothRolesEmitted()
{
@@ -75,6 +77,7 @@ public sealed class DashboardGroupRoleMapperTests
}
/// Verifies that an empty GroupToRole map yields no roles.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task MapAsync_EmptyMapping_ReturnsNoRoles()
{
@@ -92,6 +95,7 @@ public sealed class DashboardGroupRoleMapperTests
/// string LITERALS — independent of — so a
/// regression on the constant's value is caught here.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task MapAsync_AdminGroup_ResolvesToCanonicalAdministratorValue()
{
@@ -124,6 +128,7 @@ public sealed class DashboardGroupRoleMapperTests
/// Verifies the extracted shared helper is the single source of truth: it
/// produces the same roles the mapper does for the same inputs.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SharedHelper_MatchesMapperOutput()
{
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardHubsRegistrationTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardHubsRegistrationTests.cs
index 3348029..638dbd5 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardHubsRegistrationTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardHubsRegistrationTests.cs
@@ -10,6 +10,7 @@ namespace ZB.MOM.WW.MxGateway.Tests.Gateway.Dashboard;
public sealed class DashboardHubsRegistrationTests
{
/// Verifies that dashboard build maps all three hubs and token endpoint.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Build_WhenDashboardEnabled_MapsAllThreeHubsAndTokenEndpoint()
{
@@ -27,6 +28,7 @@ public sealed class DashboardHubsRegistrationTests
}
/// Verifies that dashboard build registers hub token service and connection factory.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Build_WhenDashboardEnabled_RegistersHubTokenServiceAndConnectionFactory()
{
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardSessionAdminServiceTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardSessionAdminServiceTests.cs
index 5ffa1d0..6b6367b 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardSessionAdminServiceTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardSessionAdminServiceTests.cs
@@ -10,6 +10,7 @@ namespace ZB.MOM.WW.MxGateway.Tests.Gateway.Dashboard;
public sealed class DashboardSessionAdminServiceTests
{
/// Verifies that a viewer cannot close a session.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CloseSessionAsync_ViewerCannotManage()
{
@@ -26,6 +27,7 @@ public sealed class DashboardSessionAdminServiceTests
}
/// Verifies that an admin can close a session.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CloseSessionAsync_AdminClosesSession()
{
@@ -43,6 +45,7 @@ public sealed class DashboardSessionAdminServiceTests
}
/// Verifies that closing a missing session returns a friendly error message.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CloseSessionAsync_WhenSessionMissing_ReportsFriendlyError()
{
@@ -62,6 +65,7 @@ public sealed class DashboardSessionAdminServiceTests
}
/// Verifies that a viewer cannot kill a worker.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task KillWorkerAsync_ViewerCannotManage()
{
@@ -78,6 +82,7 @@ public sealed class DashboardSessionAdminServiceTests
}
/// Verifies that an admin can kill a worker.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task KillWorkerAsync_AdminKillsWorker()
{
@@ -101,6 +106,7 @@ public sealed class DashboardSessionAdminServiceTests
}
/// Verifies that killing a worker with a blank session ID returns failure.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task KillWorkerAsync_BlankSessionId_ReturnsFailure()
{
@@ -121,6 +127,7 @@ public sealed class DashboardSessionAdminServiceTests
/// KillWorkerAsync but previously had no parallel test. Coverage was asymmetric.
/// A guard-removal regression on the close path would slip through.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CloseSessionAsync_BlankSessionId_ReturnsFailure()
{
@@ -154,6 +161,7 @@ public sealed class DashboardSessionAdminServiceTests
/// must be converted to a friendly
/// rather than propagating raw into Blazor's error boundary.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CloseSessionAsync_WhenManagerThrowsUnexpected_ReturnsFriendlyFail()
{
@@ -175,6 +183,7 @@ public sealed class DashboardSessionAdminServiceTests
///
/// Regression for Server-050: same friendly-fail contract for the Kill path.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task KillWorkerAsync_WhenManagerThrowsUnexpected_ReturnsFriendlyFail()
{
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardSnapshotPublisherTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardSnapshotPublisherTests.cs
index 6533a84..9b6b6e1 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardSnapshotPublisherTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardSnapshotPublisherTests.cs
@@ -25,6 +25,7 @@ public sealed class DashboardSnapshotPublisherTests
/// flaky on slow CI; recording firstThrowAt inside the fake removes
/// that baseline so only the Task.Delay(reconnectDelay) contributes.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ExecuteAsync_WhenSnapshotServiceThrowsOnce_ReconnectsAfterDelay()
{
@@ -75,6 +76,7 @@ public sealed class DashboardSnapshotPublisherTests
/// Sanity: a normal completion of WatchSnapshotsAsync (no exception)
/// also reconnects after the delay — exits only on host shutdown.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ExecuteAsync_WhenSnapshotServiceCompletes_ReconnectsAfterDelay()
{
@@ -124,14 +126,13 @@ public sealed class DashboardSnapshotPublisherTests
/// Gets the wall-clock instant of the second subscription attempt.
public DateTimeOffset? SecondSubscribeAt { get; private set; }
- /// Gets the current snapshot.
+ ///
public DashboardSnapshot GetSnapshot()
{
return null!;
}
- /// Watches for snapshot changes and yields them asynchronously.
- /// Token to observe for cancellation.
+ ///
public async IAsyncEnumerable WatchSnapshotsAsync(
[EnumeratorCancellation] CancellationToken cancellationToken)
{
@@ -167,14 +168,13 @@ public sealed class DashboardSnapshotPublisherTests
/// Gets the number of subscription attempts.
public int SubscribeCount { get; private set; }
- /// Gets the current snapshot.
+ ///
public DashboardSnapshot GetSnapshot()
{
return null!;
}
- /// Watches for snapshot changes and completes immediately.
- /// Token to observe for cancellation.
+ ///
#pragma warning disable CS1998 // async without await — IAsyncEnumerable contract requires async signature
public async IAsyncEnumerable WatchSnapshotsAsync(
[EnumeratorCancellation] CancellationToken cancellationToken)
@@ -211,35 +211,43 @@ public sealed class DashboardSnapshotPublisherTests
/// Gets a client proxy excluding specified connections.
/// Connection identifiers to exclude.
+ /// A client proxy targeting all clients except the specified connections.
public IClientProxy AllExcept(IReadOnlyList excludedConnectionIds) => AllProxy;
/// Gets a client proxy for a specific connection.
/// The connection identifier.
+ /// A client proxy targeting the specified connection.
public IClientProxy Client(string connectionId) => AllProxy;
/// Gets a client proxy for specified connections.
/// The connection identifiers.
+ /// A client proxy targeting the specified connections.
public IClientProxy Clients(IReadOnlyList connectionIds) => AllProxy;
/// Gets a client proxy for a group.
/// The group name.
+ /// A client proxy targeting the specified group.
public IClientProxy Group(string groupName) => AllProxy;
/// Gets a client proxy for a group excluding specified connections.
/// The group name.
/// Connection identifiers to exclude.
+ /// A client proxy targeting the group except the excluded connections.
public IClientProxy GroupExcept(string groupName, IReadOnlyList excludedConnectionIds) => AllProxy;
/// Gets a client proxy for specified groups.
/// The group names.
+ /// A client proxy targeting the specified groups.
public IClientProxy Groups(IReadOnlyList groupNames) => AllProxy;
/// Gets a client proxy for a specific user.
/// The user identifier.
+ /// A client proxy targeting the specified user.
public IClientProxy User(string userId) => AllProxy;
/// Gets a client proxy for specified users.
/// The user identifiers.
+ /// A client proxy targeting the specified users.
public IClientProxy Users(IReadOnlyList userIds) => AllProxy;
}
@@ -254,6 +262,7 @@ public sealed class DashboardSnapshotPublisherTests
/// The SignalR method name.
/// The method arguments.
/// Token to observe for cancellation.
+ /// A task that represents the asynchronous operation.
public Task SendCoreAsync(string method, object?[] args, CancellationToken cancellationToken = default)
{
Interlocked.Increment(ref _sendCount);
@@ -267,6 +276,7 @@ public sealed class DashboardSnapshotPublisherTests
/// The connection identifier.
/// The group name.
/// Token to observe for cancellation.
+ /// A task that represents the asynchronous operation.
public Task AddToGroupAsync(string connectionId, string groupName, CancellationToken cancellationToken = default)
=> Task.CompletedTask;
@@ -274,6 +284,7 @@ public sealed class DashboardSnapshotPublisherTests
/// The connection identifier.
/// The group name.
/// Token to observe for cancellation.
+ /// A task that represents the asynchronous operation.
public Task RemoveFromGroupAsync(string connectionId, string groupName, CancellationToken cancellationToken = default)
=> Task.CompletedTask;
}
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardSnapshotServiceTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardSnapshotServiceTests.cs
index a50b374..c43db95 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardSnapshotServiceTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Dashboard/DashboardSnapshotServiceTests.cs
@@ -269,6 +269,7 @@ public sealed class DashboardSnapshotServiceTests
}
/// Verifies that snapshot service refreshes API key summaries before each snapshot.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WatchSnapshotsAsync_RefreshesApiKeySummariesBeforeSnapshot()
{
@@ -305,6 +306,7 @@ public sealed class DashboardSnapshotServiceTests
}
/// Verifies that snapshot service reuses previous summaries when API key refresh fails.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WatchSnapshotsAsync_WhenApiKeyRefreshFails_ReusesPreviousSummaries()
{
@@ -348,6 +350,7 @@ public sealed class DashboardSnapshotServiceTests
}
/// Verifies that snapshot service disposes cleanly when subscriber cancels.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WatchSnapshotsAsync_WhenSubscriberCancels_DisposesCleanly()
{
@@ -401,53 +404,59 @@ public sealed class DashboardSnapshotServiceTests
private sealed class StubGalaxyHierarchyCache(GalaxyHierarchyCacheEntry current) : IGalaxyHierarchyCache
{
- ///
- /// Gets the current Galaxy hierarchy cache entry.
- ///
+ ///
public GalaxyHierarchyCacheEntry Current { get; } = current;
- ///
- /// Refreshes the cache asynchronously.
- ///
- /// Cancellation token.
- /// Completed task.
+ ///
public Task RefreshAsync(CancellationToken cancellationToken) => Task.CompletedTask;
- ///
- /// Waits for the first cache load asynchronously.
- ///
- /// Cancellation token.
- /// Completed task.
+ ///
public Task WaitForFirstLoadAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
private class FakeApiKeyAdminStore : IApiKeyAdminStore
{
- ///
+ /// Stores the record; always succeeds.
+ /// The API key record to create.
+ /// Cancellation token.
+ /// A task that represents the asynchronous operation.
public Task CreateAsync(ApiKeyRecord record, CancellationToken ct)
{
return Task.CompletedTask;
}
- ///
+ /// Returns an empty list of API key items.
+ /// Cancellation token.
+ /// A task that resolves to an empty read-only list.
public virtual Task> ListAsync(CancellationToken ct)
{
return Task.FromResult>([]);
}
- ///
+ /// Marks the key revoked; always returns false (key not found).
+ /// The key identifier.
+ /// Revocation timestamp.
+ /// Cancellation token.
+ /// A task that resolves to false.
public Task RevokeAsync(string keyId, DateTimeOffset whenUtc, CancellationToken ct)
{
return Task.FromResult(false);
}
- ///
+ /// Rotates the key secret; always returns false (key not found).
+ /// The key identifier.
+ /// The new secret hash bytes.
+ /// Cancellation token.
+ /// A task that resolves to false.
public Task RotateAsync(string keyId, byte[] newSecretHash, CancellationToken ct)
{
return Task.FromResult(false);
}
- ///
+ /// Deletes the key; always returns false (key not found).
+ /// The key identifier.
+ /// Cancellation token.
+ /// A task that resolves to false.
public Task DeleteAsync(string keyId, CancellationToken ct)
{
return Task.FromResult(false);
@@ -512,24 +521,16 @@ public sealed class DashboardSnapshotServiceTests
int? processId,
WorkerClientState state) : IWorkerClient
{
- ///
- /// Gets the session identifier.
- ///
+ ///
public string SessionId { get; } = sessionId;
- ///
- /// Gets the process identifier.
- ///
+ ///
public int? ProcessId { get; } = processId;
- ///
- /// Gets the current worker client state.
- ///
+ ///
public WorkerClientState State { get; private set; } = state;
- ///
- /// Gets the timestamp of the last heartbeat.
- ///
+ ///
public DateTimeOffset LastHeartbeatAt { get; } = DateTimeOffset.Parse("2026-04-26T10:02:00Z", CultureInfo.InvariantCulture);
///
@@ -547,24 +548,14 @@ public sealed class DashboardSnapshotServiceTests
///
public int KillCount { get; private set; }
- ///
- /// Starts the worker client asynchronously.
- ///
- /// Cancellation token.
- /// Completed task.
+ ///
public Task StartAsync(CancellationToken cancellationToken)
{
StartCount++;
return Task.CompletedTask;
}
- ///
- /// Invokes a worker command asynchronously.
- ///
- /// The command to invoke.
- /// Command timeout.
- /// Cancellation token.
- /// Command reply.
+ ///
public Task InvokeAsync(
WorkerCommand command,
TimeSpan timeout,
@@ -573,11 +564,7 @@ public sealed class DashboardSnapshotServiceTests
return Task.FromResult(new WorkerCommandReply());
}
- ///
- /// Reads events from the worker asynchronously.
- ///
- /// Cancellation token.
- /// Async enumerable of worker events.
+ ///
public async IAsyncEnumerable ReadEventsAsync(
[System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken)
{
@@ -585,12 +572,7 @@ public sealed class DashboardSnapshotServiceTests
yield break;
}
- ///
- /// Shuts down the worker client asynchronously.
- ///
- /// Shutdown timeout.
- /// Cancellation token.
- /// Completed task.
+ ///
public Task ShutdownAsync(
TimeSpan timeout,
CancellationToken cancellationToken)
@@ -600,20 +582,15 @@ public sealed class DashboardSnapshotServiceTests
return Task.CompletedTask;
}
- ///
- /// Terminates the worker client.
- ///
- /// Reason for termination.
+ ///
public void Kill(string reason)
{
KillCount++;
State = WorkerClientState.Faulted;
}
- ///
- /// Releases resources used by this worker client.
- ///
- /// Completed value task.
+ /// Disposes the fake worker client; no-op for testing.
+ /// A completed task.
public ValueTask DisposeAsync()
{
return ValueTask.CompletedTask;
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/GatewayApplicationTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/GatewayApplicationTests.cs
index 98ee67e..9b81458 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/GatewayApplicationTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/GatewayApplicationTests.cs
@@ -15,6 +15,7 @@ namespace ZB.MOM.WW.MxGateway.Tests.Gateway;
public sealed class GatewayApplicationTests
{
/// Verifies that Build maps the canonical three health tiers.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Build_MapsCanonicalHealthEndpoints()
{
@@ -42,6 +43,7 @@ public sealed class GatewayApplicationTests
}
/// Verifies that Build registers the gateway metrics service.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Build_RegistersGatewayMetrics()
{
@@ -53,6 +55,7 @@ public sealed class GatewayApplicationTests
}
/// Verifies that Build mounts the Prometheus /metrics scrape endpoint.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Build_MapsMetricsEndpoint()
{
@@ -75,6 +78,7 @@ public sealed class GatewayApplicationTests
}
/// Verifies that Build maps dashboard and authentication endpoints when the dashboard is enabled.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Build_WhenDashboardEnabled_MapsBlazorDashboardAndAuthEndpoints()
{
@@ -99,6 +103,7 @@ public sealed class GatewayApplicationTests
}
/// Verifies that the dashboard login, logout, and denied endpoints allow anonymous access.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Build_WhenDashboardEnabled_AuthEndpointsAllowAnonymousAccess()
{
@@ -128,6 +133,7 @@ public sealed class GatewayApplicationTests
}
/// Verifies that dashboard Razor component routes require the dashboard viewer policy.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Build_WhenDashboardEnabled_ComponentRoutesRequireAuthorization()
{
@@ -156,6 +162,7 @@ public sealed class GatewayApplicationTests
}
/// Verifies that dashboard routes are registered at root when enabled.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Build_WhenDashboardEnabled_RegistersDashboardRoutesAtRoot()
{
@@ -181,6 +188,7 @@ public sealed class GatewayApplicationTests
}
/// Verifies that dashboard routes are not mapped when disabled.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Build_WhenDashboardDisabled_DoesNotMapDashboardRoutes()
{
@@ -197,6 +205,7 @@ public sealed class GatewayApplicationTests
/// Configuration key to override.
/// Invalid configuration value.
/// Expected validation error message.
+ /// A task that represents the asynchronous operation.
[Theory]
[InlineData(
"MxGateway:Worker:ExecutablePath",
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/GatewayEndToEndFakeWorkerSmokeTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/GatewayEndToEndFakeWorkerSmokeTests.cs
index 2185f29..1c53116 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/GatewayEndToEndFakeWorkerSmokeTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/GatewayEndToEndFakeWorkerSmokeTests.cs
@@ -25,6 +25,7 @@ public sealed class GatewayEndToEndFakeWorkerSmokeTests
///
/// Verifies gateway session lifecycle with a scripted fake worker: open, command, event, close.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task GatewayService_WithFakeWorker_CompletesSessionCommandEventAndClosePath()
{
@@ -201,6 +202,7 @@ public sealed class GatewayEndToEndFakeWorkerSmokeTests
///
/// Disposes all active sessions and metrics.
///
+ /// A value task that represents the asynchronous disposal.
public async ValueTask DisposeAsync()
{
foreach (GatewaySession session in _registry.Snapshot())
@@ -256,12 +258,7 @@ public sealed class GatewayEndToEndFakeWorkerSmokeTests
///
public Task WorkerTask { get; private set; } = Task.CompletedTask;
- ///
- /// Launches a new worker process and returns a handle to manage it.
- ///
- /// Worker process launch request parameters.
- /// Cancellation token.
- /// Worker process handle.
+ ///
public Task LaunchAsync(
WorkerProcessLaunchRequest request,
CancellationToken cancellationToken = default)
@@ -359,37 +356,22 @@ public sealed class GatewayEndToEndFakeWorkerSmokeTests
{
private readonly TaskCompletionSource _exited = new(TaskCreationOptions.RunContinuationsAsynchronously);
- ///
- /// Gets the process identifier.
- ///
+ ///
public int Id { get; } = processId;
- ///
- /// Gets a value indicating whether the process has exited.
- ///
+ ///
public bool HasExited { get; private set; }
- ///
- /// Gets the exit code of the process.
- ///
+ ///
public int? ExitCode { get; private set; }
- ///
- /// Waits for the process to exit asynchronously. Completes only when
- /// or has been called, so callers that observe completion can
- /// trust that exit actually happened (e.g., via the worker shutdown-ack path).
- ///
- /// Cancellation token.
- /// A task that completes when the process has actually exited.
+ ///
public ValueTask WaitForExitAsync(CancellationToken cancellationToken)
{
return new ValueTask(_exited.Task.WaitAsync(cancellationToken));
}
- ///
- /// Terminates the process.
- ///
- /// Whether to kill the entire process tree.
+ ///
public void Kill(bool entireProcessTree)
{
MarkExited(-1);
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/GatewayTlsBootstrapTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/GatewayTlsBootstrapTests.cs
index f34d698..38cc3c9 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/GatewayTlsBootstrapTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/GatewayTlsBootstrapTests.cs
@@ -21,6 +21,7 @@ public sealed class GatewayTlsBootstrapTests
/// trusted dev cert, Kestrel would otherwise serve that dev cert (CN=localhost), so the
/// subject assertion is what makes this test fail without the wiring on either kind of host.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Host_ServesGeneratedCertificate_WhenHttpsEndpointHasNoCertificate()
{
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/EventStreamServiceTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/EventStreamServiceTests.cs
index 6f45a15..f7af36f 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/EventStreamServiceTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/EventStreamServiceTests.cs
@@ -18,6 +18,7 @@ public sealed class EventStreamServiceTests
private static readonly TimeSpan TestTimeout = TimeSpan.FromSeconds(5);
/// Verifies that events from the worker stream maintain their original sequence order.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task StreamEventsAsync_YieldsEventsInWorkerOrder()
{
@@ -39,6 +40,7 @@ public sealed class EventStreamServiceTests
}
/// Verifies that a second event subscriber is rejected when one is already active.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task StreamEventsAsync_WhenSecondSubscriberStarts_RejectsClearly()
{
@@ -68,6 +70,7 @@ public sealed class EventStreamServiceTests
}
/// Verifies that canceling an event stream detaches the subscriber cleanly.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task StreamEventsAsync_WhenCanceled_DetachesSubscriber()
{
@@ -90,6 +93,7 @@ public sealed class EventStreamServiceTests
}
/// Verifies that disposing an event stream with buffered events resets the queue depth metric.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task StreamEventsAsync_WhenDisposedWithBufferedEvents_ResetsStreamQueueDepth()
{
@@ -117,6 +121,7 @@ public sealed class EventStreamServiceTests
}
/// Verifies that queue depth metrics correctly track concurrent event streams across multiple sessions.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task StreamEventsAsync_WithConcurrentStreams_TracksAggregateQueueDepth()
{
@@ -158,6 +163,7 @@ public sealed class EventStreamServiceTests
}
/// Verifies that event queue overflow faults the session and reports the overflow metric.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task StreamEventsAsync_WhenStreamQueueOverflows_FaultsSessionAndReportsOverflow()
{
@@ -188,6 +194,7 @@ public sealed class EventStreamServiceTests
}
/// Verifies that the disconnect backpressure policy disconnects the subscriber without faulting the session.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task StreamEventsAsync_WhenStreamQueueOverflowsWithDisconnectPolicy_LeavesSessionReady()
{
@@ -220,6 +227,7 @@ public sealed class EventStreamServiceTests
}
/// Verifies that the event stream does not synthesize OperationComplete events from write completions.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task StreamEventsAsync_DoesNotSynthesizeOperationComplete()
{
@@ -237,6 +245,7 @@ public sealed class EventStreamServiceTests
}
/// Verifies that a terminal fault from the worker event stream propagates and faults the session.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task StreamEventsAsync_WhenWorkerEventStreamFaults_PropagatesTerminalFault()
{
@@ -273,6 +282,7 @@ public sealed class EventStreamServiceTests
/// assert one publish per yielded event, with the correct session id and
/// preserved WorkerSequence.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task StreamEventsAsync_PublishesEachEventToDashboardBroadcaster()
{
@@ -308,6 +318,7 @@ public sealed class EventStreamServiceTests
/// surface the exception and the client would see a faulted stream
/// for a dashboard-mirror failure.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task StreamEventsAsync_WhenDashboardBroadcasterThrows_StillYieldsEventsAndDoesNotFaultSession()
{
@@ -358,9 +369,7 @@ public sealed class EventStreamServiceTests
/// Gets the count of publish attempts.
public int PublishAttempts { get; private set; }
- /// Increments the attempt count and throws a simulated failure.
- /// The session identifier.
- /// The event to publish.
+ ///
public void Publish(string sessionId, MxEvent mxEvent)
{
PublishAttempts++;
@@ -610,7 +619,8 @@ public sealed class EventStreamServiceTests
State = WorkerClientState.Faulted;
}
- ///
+ /// Disposes the fake worker client.
+ /// A completed value task.
public ValueTask DisposeAsync()
{
return ValueTask.CompletedTask;
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/GalaxyRepositoryGrpcServiceTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/GalaxyRepositoryGrpcServiceTests.cs
index ee05cb9..d5ddd06 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/GalaxyRepositoryGrpcServiceTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/GalaxyRepositoryGrpcServiceTests.cs
@@ -13,6 +13,7 @@ namespace ZB.MOM.WW.MxGateway.Tests.Gateway.Grpc;
public sealed class GalaxyRepositoryGrpcServiceTests
{
/// Verifies that DiscoverHierarchy returns the requested page and totals.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DiscoverHierarchy_ReturnsRequestedPageAndTotals()
{
@@ -34,6 +35,7 @@ public sealed class GalaxyRepositoryGrpcServiceTests
}
/// Verifies that DiscoverHierarchy with a page token returns remaining objects.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DiscoverHierarchy_WithNextPageToken_ReturnsRemainingObjects()
{
@@ -62,6 +64,7 @@ public sealed class GalaxyRepositoryGrpcServiceTests
/// Verifies that DiscoverHierarchy with invalid paging arguments returns InvalidArgument.
/// The page token to test.
/// The page size to test.
+ /// A task that represents the asynchronous operation.
[Theory]
[InlineData("-1", 1)]
[InlineData("not-an-offset", 1)]
@@ -87,6 +90,7 @@ public sealed class GalaxyRepositoryGrpcServiceTests
}
/// Verifies that DiscoverHierarchy with subtree root and depth filters descendants.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DiscoverHierarchy_WithSubtreeRootAndDepth_FiltersDescendants()
{
@@ -106,6 +110,7 @@ public sealed class GalaxyRepositoryGrpcServiceTests
}
/// Verifies that DiscoverHierarchy applies server-side filters and omits attributes.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DiscoverHierarchy_WithServerSideFilters_AppliesAllFiltersAndOmitsAttributes()
{
@@ -132,6 +137,7 @@ public sealed class GalaxyRepositoryGrpcServiceTests
}
/// Verifies that DiscoverHierarchy with filtered paging returns post-filter total.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DiscoverHierarchy_WithFilteredPaging_ReturnsPostFilterTotal()
{
@@ -164,6 +170,7 @@ public sealed class GalaxyRepositoryGrpcServiceTests
}
/// Verifies that DiscoverHierarchy with mismatched filter token returns InvalidArgument.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DiscoverHierarchy_WithMismatchedFilterToken_ReturnsInvalidArgument()
{
@@ -191,6 +198,7 @@ public sealed class GalaxyRepositoryGrpcServiceTests
}
/// Verifies that DiscoverHierarchy with missing root returns NotFound.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DiscoverHierarchy_WithMissingRoot_ReturnsNotFound()
{
@@ -337,6 +345,7 @@ public sealed class GalaxyRepositoryGrpcServiceTests
}
/// Verifies that BrowseChildren returns root objects and the current cache sequence when called with no parent.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task BrowseChildren_RootCall_ReturnsRootsWithCacheSequence()
{
@@ -355,6 +364,7 @@ public sealed class GalaxyRepositoryGrpcServiceTests
}
/// Verifies that BrowseChildren returns Unavailable when the cache's first load never completes.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task BrowseChildren_FirstLoadNotComplete_ReturnsUnavailable()
{
@@ -381,6 +391,7 @@ public sealed class GalaxyRepositoryGrpcServiceTests
}
/// Verifies that a page token bound to a stale cache sequence is rejected with InvalidArgument.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task BrowseChildren_StaleToken_ReturnsInvalidArgument()
{
@@ -407,6 +418,7 @@ public sealed class GalaxyRepositoryGrpcServiceTests
}
/// Verifies that switching filters between paged BrowseChildren calls is rejected.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task BrowseChildren_FilterChangeBetweenPages_ReturnsInvalidArgument()
{
@@ -436,6 +448,7 @@ public sealed class GalaxyRepositoryGrpcServiceTests
}
/// Verifies that an ApiKeyIdentity browse-subtrees constraint that matches nothing produces an empty child list.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task BrowseChildren_BrowseSubtreesConstraint_FiltersChildren()
{
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/MxAccessGatewayServiceConstraintTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/MxAccessGatewayServiceConstraintTests.cs
index a01cfb8..4fad5fe 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/MxAccessGatewayServiceConstraintTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/MxAccessGatewayServiceConstraintTests.cs
@@ -34,6 +34,7 @@ public sealed class MxAccessGatewayServiceConstraintTests
/// worker once with only the allowed tags, then splice the denied entries
/// back into the reply at their original indices.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Invoke_AddItemBulk_WithMixedDenials_InterleavesDeniedAndAllowedInOriginalIndexOrder()
{
@@ -95,6 +96,7 @@ public sealed class MxAccessGatewayServiceConstraintTests
/// false, return the
/// denied-only reply, and never call the session manager.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Invoke_SubscribeBulk_WhenAllTagsDenied_DoesNotCallWorkerAndReturnsDeniedReply()
{
@@ -118,6 +120,7 @@ public sealed class MxAccessGatewayServiceConstraintTests
/// FilterHandleBulkAsync against CheckReadHandleAsync. Partial
/// denial must still produce a merged-by-index BulkSubscribeReply.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Invoke_AdviseItemBulk_WithMixedHandleDenials_MergesDeniedIntoReply()
{
@@ -166,6 +169,7 @@ public sealed class MxAccessGatewayServiceConstraintTests
/// unchanged — the constraint plan is null and no merge occurs. Regression
/// guard against accidentally engaging the merge path for the common case.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Invoke_SubscribeBulk_WithAllowAllEnforcer_PassesThroughUnchanged()
{
@@ -208,6 +212,7 @@ public sealed class MxAccessGatewayServiceConstraintTests
/// the SubscribeBulk family because the reply slot is
/// BulkReadReply, not BulkSubscribeReply.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Invoke_ReadBulk_WithMixedDenials_MergesDeniedBulkReadResults()
{
@@ -255,6 +260,7 @@ public sealed class MxAccessGatewayServiceConstraintTests
/// 's ReadBulkConstraintPlan
/// CreateDeniedReply path.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Invoke_ReadBulk_WhenAllTagsDenied_ShortCircuitsWithDeniedOnlyReply()
{
@@ -279,6 +285,7 @@ public sealed class MxAccessGatewayServiceConstraintTests
/// forwarded command and splice a denied BulkWriteResult back in at
/// the original index.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Invoke_WriteBulk_WithDeniedHandle_DropsEntryFromWorkerCallAndMergesDenialIntoReply()
{
@@ -329,6 +336,7 @@ public sealed class MxAccessGatewayServiceConstraintTests
/// switch arm than plain WriteBulk. The merge logic is shared, so a
/// full denial here is enough to prove the secured-bulk routing.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Invoke_WriteSecuredBulk_WhenAllHandlesDenied_ShortCircuitsWithDeniedOnlyReply()
{
@@ -354,6 +362,7 @@ public sealed class MxAccessGatewayServiceConstraintTests
/// (and not, say, WriteBulk by mistake) — guarding against a refactor that
/// drops or misroutes the Write2Bulk case.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Invoke_Write2Bulk_WhenAllHandlesDenied_ShortCircuitsWithDeniedOnlyReply()
{
@@ -382,6 +391,7 @@ public sealed class MxAccessGatewayServiceConstraintTests
/// Write2Bulk — assert the WriteSecured2Bulk reply slot is populated
/// to prove that arm of the switch fires.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Invoke_WriteSecured2Bulk_WhenAllHandlesDenied_ShortCircuitsWithDeniedOnlyReply()
{
@@ -417,6 +427,7 @@ public sealed class MxAccessGatewayServiceConstraintTests
/// This fixture makes that "silent truncate" behaviour explicit so a future
/// change either fills the gap with a synthetic failure or fails this test.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Invoke_WriteBulk_WhenWorkerReturnsFewerResultsThanAllowed_MergedReplyIsTruncated()
{
@@ -470,6 +481,7 @@ public sealed class MxAccessGatewayServiceConstraintTests
/// for index < OriginalCount loop bound so a regression that
/// accidentally surfaces extras as trailing results is caught.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Invoke_WriteBulk_WhenWorkerReturnsExtraResults_IgnoresExtras()
{
@@ -527,6 +539,7 @@ public sealed class MxAccessGatewayServiceConstraintTests
/// via EnforceWriteHandleAsync
/// and never reach the session manager.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Invoke_Write_WithDeniedHandle_ThrowsPermissionDeniedAndDoesNotCallWorker()
{
@@ -554,6 +567,7 @@ public sealed class MxAccessGatewayServiceConstraintTests
/// ApplyConstraintsAsync (Write/Write2/WriteSecured/WriteSecured2) is
/// reachable for at least one of the secured kinds.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Invoke_WriteSecured_WithDeniedHandle_ThrowsPermissionDenied()
{
@@ -577,6 +591,7 @@ public sealed class MxAccessGatewayServiceConstraintTests
/// via EnforceReadTagAsync
/// and never reach the session manager.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Invoke_AddItem_WithDeniedTag_ThrowsPermissionDeniedAndDoesNotCallWorker()
{
@@ -854,19 +869,14 @@ public sealed class MxAccessGatewayServiceConstraintTests
/// The session to seed.
public void SeedSession(GatewaySession session) => seededSessions[session.SessionId] = session;
- /// Opens a test session asynchronously.
- /// The session open request.
- /// The client identity, if any.
- /// Token to observe for cancellation.
+ ///
public Task OpenSessionAsync(
SessionOpenRequest request,
string? clientIdentity,
CancellationToken cancellationToken) =>
Task.FromResult(seededSessions.Values.First());
- /// Tries to get a test session by identifier.
- /// The session identifier.
- /// The session, if found.
+ ///
public bool TryGetSession(string sessionId, out GatewaySession session)
{
if (seededSessions.TryGetValue(sessionId, out GatewaySession? seeded))
@@ -885,10 +895,7 @@ public sealed class MxAccessGatewayServiceConstraintTests
return true;
}
- /// Invokes a worker command and returns the reply asynchronously.
- /// The session identifier.
- /// The worker command.
- /// Token to observe for cancellation.
+ ///
public Task InvokeAsync(
string sessionId,
WorkerCommand command,
@@ -899,9 +906,7 @@ public sealed class MxAccessGatewayServiceConstraintTests
return Task.FromResult(InvokeReply);
}
- /// Reads events from the session asynchronously.
- /// The session identifier.
- /// Token to observe for cancellation.
+ ///
public async IAsyncEnumerable ReadEventsAsync(
string sessionId,
[System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken)
@@ -914,33 +919,25 @@ public sealed class MxAccessGatewayServiceConstraintTests
}
}
- /// Closes a test session asynchronously.
- /// The session identifier.
- /// Token to observe for cancellation.
+ ///
public Task CloseSessionAsync(
string sessionId,
CancellationToken cancellationToken) =>
Task.FromResult(new SessionCloseResult(sessionId, SessionState.Closed, AlreadyClosed: false));
- /// Kills a worker process asynchronously.
- /// The session identifier.
- /// The reason for killing the worker.
- /// Token to observe for cancellation.
+ ///
public Task KillWorkerAsync(
string sessionId,
string reason,
CancellationToken cancellationToken) =>
Task.FromResult(new SessionCloseResult(sessionId, SessionState.Closed, AlreadyClosed: false));
- /// Closes expired session leases asynchronously.
- /// The current time to check against.
- /// Token to observe for cancellation.
+ ///
public Task CloseExpiredLeasesAsync(
DateTimeOffset now,
CancellationToken cancellationToken) => Task.FromResult(0);
- /// Shuts down the test session manager asynchronously.
- /// Token to observe for cancellation.
+ ///
public Task ShutdownAsync(CancellationToken cancellationToken) => Task.CompletedTask;
private static GatewaySession CreateFallbackSession(string sessionId)
@@ -965,9 +962,7 @@ public sealed class MxAccessGatewayServiceConstraintTests
private sealed class FakeEventStreamService(FakeSessionManager sessionManager) : IEventStreamService
{
- /// Streams events for the test session asynchronously.
- /// The stream events request.
- /// Token to observe for cancellation.
+ ///
public async IAsyncEnumerable StreamEventsAsync(
StreamEventsRequest request,
[System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken)
@@ -983,33 +978,28 @@ public sealed class MxAccessGatewayServiceConstraintTests
private sealed class FakeWorkerClient : IWorkerClient
{
- /// Gets the test session identifier.
+ ///
public string SessionId { get; } = MxAccessGatewayServiceConstraintTests.SessionId;
- /// Gets the test worker process identifier.
+ ///
public int? ProcessId { get; } = 1234;
- /// Gets the test worker client state.
+ ///
public WorkerClientState State { get; } = WorkerClientState.Ready;
- /// Gets the last recorded heartbeat time.
+ ///
public DateTimeOffset LastHeartbeatAt { get; } = DateTimeOffset.UtcNow;
- /// Starts the test worker client asynchronously.
- /// Token to observe for cancellation.
+ ///
public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask;
- /// Invokes a command on the test worker asynchronously.
- /// The worker command.
- /// Maximum time to wait for completion.
- /// Token to observe for cancellation.
+ ///
public Task InvokeAsync(
WorkerCommand command,
TimeSpan timeout,
CancellationToken cancellationToken) => Task.FromResult(new WorkerCommandReply());
- /// Reads events from the test worker asynchronously.
- /// Token to observe for cancellation.
+ ///
public async IAsyncEnumerable ReadEventsAsync(
[System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken)
{
@@ -1017,18 +1007,16 @@ public sealed class MxAccessGatewayServiceConstraintTests
yield break;
}
- /// Shuts down the test worker client asynchronously.
- /// Maximum time to wait for completion.
- /// Token to observe for cancellation.
+ ///
public Task ShutdownAsync(TimeSpan timeout, CancellationToken cancellationToken) => Task.CompletedTask;
- /// Kills the test worker process.
- /// The reason for killing the worker.
+ ///
public void Kill(string reason)
{
}
- ///
+ /// Releases resources held by this fake worker client asynchronously.
+ /// A completed value task.
public ValueTask DisposeAsync() => ValueTask.CompletedTask;
}
}
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/MxAccessGatewayServiceTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/MxAccessGatewayServiceTests.cs
index cacda2e..9eac234 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/MxAccessGatewayServiceTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Grpc/MxAccessGatewayServiceTests.cs
@@ -18,6 +18,7 @@ namespace ZB.MOM.WW.MxGateway.Tests.Gateway.Grpc;
public sealed class MxAccessGatewayServiceTests
{
/// Verifies that OpenSession returns correct session details for a valid request.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task OpenSession_WithValidRequest_ReturnsSessionDetails()
{
@@ -55,6 +56,7 @@ public sealed class MxAccessGatewayServiceTests
/// TryGetSession return false, so this test fails if the service drops
/// its missing-session check rather than passing for the wrong reason.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Invoke_WhenSessionMissing_ThrowsNotFound()
{
@@ -77,6 +79,7 @@ public sealed class MxAccessGatewayServiceTests
/// manager when is on,
/// confirming the missing-session test above is gated on a real lookup.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Invoke_WhenSessionSeeded_ResolvesAndInvokes()
{
@@ -93,6 +96,7 @@ public sealed class MxAccessGatewayServiceTests
}
/// Verifies that Invoke throws InvalidArgument and does not invoke the session manager when payload is mismatched.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Invoke_WithMismatchedPayload_ThrowsInvalidArgumentAndDoesNotCallSessionManager()
{
@@ -116,6 +120,7 @@ public sealed class MxAccessGatewayServiceTests
}
/// Verifies that Invoke returns HResult status and method payload from worker reply.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Invoke_WithWorkerReply_ReturnsHresultStatusAndMethodPayload()
{
@@ -171,6 +176,7 @@ public sealed class MxAccessGatewayServiceTests
}
/// Verifies that StreamEvents writes only events after the specified worker sequence.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task StreamEvents_WithAfterSequence_WritesOnlyLaterEvents()
{
@@ -205,6 +211,7 @@ public sealed class MxAccessGatewayServiceTests
///
/// regression for the cross-talk reproduction.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task StreamEvents_WhenEventIsWritten_RecordsSendDuration()
{
@@ -258,6 +265,7 @@ public sealed class MxAccessGatewayServiceTests
/// caused StreamEvents_WhenEventIsWritten_RecordsSendDuration to fail intermittently when
/// run in parallel with another test recording the same histogram.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task StreamEvents_RecordSendDurationListener_IgnoresMeasurementsFromOtherMetersWithSameName()
{
@@ -314,6 +322,7 @@ public sealed class MxAccessGatewayServiceTests
}
/// Verifies that CloseSession throws InvalidArgument when session ID is blank.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CloseSession_WithBlankSessionId_ThrowsInvalidArgument()
{
@@ -334,6 +343,7 @@ public sealed class MxAccessGatewayServiceTests
// alarm feed. CreateService injects FakeGatewayAlarmService.
/// Verifies AcknowledgeAlarm rejects an empty alarm_full_reference.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AcknowledgeAlarm_WithMissingAlarmReference_ThrowsInvalidArgument()
{
@@ -348,6 +358,7 @@ public sealed class MxAccessGatewayServiceTests
}
/// Verifies AcknowledgeAlarm delegates a valid request to the alarm service.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AcknowledgeAlarm_WithValidRequest_DelegatesToAlarmService()
{
@@ -368,6 +379,7 @@ public sealed class MxAccessGatewayServiceTests
}
/// Verifies StreamAlarms forwards the central alarm feed, ending with snapshot_complete.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task StreamAlarms_ForwardsTheCentralAlarmFeed()
{
@@ -385,6 +397,7 @@ public sealed class MxAccessGatewayServiceTests
}
/// Verifies OpenSession advertises the alarm RPC capability strings.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task OpenSession_AdvertisesAlarmRpcCapabilities()
{
@@ -709,7 +722,8 @@ public sealed class MxAccessGatewayServiceTests
{
}
- ///
+ /// Releases resources held by this fake worker client.
+ /// A completed value task.
public ValueTask DisposeAsync()
{
return ValueTask.CompletedTask;
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/GatewaySessionTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/GatewaySessionTests.cs
index 403e532..d2e53c0 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/GatewaySessionTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/GatewaySessionTests.cs
@@ -21,6 +21,7 @@ public sealed class GatewaySessionTests
/// Closing write and the Closed write, which is precisely the
/// window the audit identified.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task TransitionTo_AfterCloseStarted_DoesNotOverwriteClosing()
{
@@ -53,6 +54,7 @@ public sealed class GatewaySessionTests
/// terminal write goes through the same _syncRoot the rest of the state
/// machine uses, so the existing "Closed is terminal" invariant holds.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task MarkFaulted_AfterCloseCompletes_DoesNotResurrectSession()
{
@@ -79,6 +81,7 @@ public sealed class GatewaySessionTests
/// Faulted" — this test pins the resolved end state so a future tightening
/// of MarkFaulted cannot silently regress it.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task MarkFaulted_DuringInFlightClose_PreservesFaultButYieldsToClose()
{
@@ -111,6 +114,7 @@ public sealed class GatewaySessionTests
/// its semaphore. Without the fix, the close's _closeLock.Release()
/// would race the dispose and raise .
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DisposeAsync_WhileCloseInFlight_WaitsForCloseAndDoesNotThrow()
{
@@ -142,6 +146,7 @@ public sealed class GatewaySessionTests
/// from the already-disposed semaphore
/// rather than propagating it.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DisposeAsync_CalledTwice_DoesNotThrow()
{
@@ -187,16 +192,16 @@ public sealed class GatewaySessionTests
private readonly TaskCompletionSource _shutdownStarted = new(TaskCreationOptions.RunContinuationsAsynchronously);
private readonly TaskCompletionSource _shutdownReleased = new(TaskCreationOptions.RunContinuationsAsynchronously);
- /// Gets the session identifier.
+ ///
public string SessionId { get; } = "session-test";
- /// Gets the worker process identifier.
+ ///
public int? ProcessId { get; } = 1234;
- /// Gets or sets the worker client state.
+ ///
public WorkerClientState State { get; private set; } = WorkerClientState.Ready;
- /// Gets the last recorded heartbeat timestamp.
+ ///
public DateTimeOffset LastHeartbeatAt { get; } = DateTimeOffset.UtcNow;
/// Gets the count of shutdown invocations.
@@ -206,6 +211,7 @@ public sealed class GatewaySessionTests
public int DisposeCount { get; private set; }
/// Waits for shutdown to start.
+ /// A task that represents the asynchronous operation.
public Task WaitForShutdownStartAsync()
{
return _shutdownStarted.Task.WaitAsync(TimeSpan.FromSeconds(5));
@@ -249,7 +255,8 @@ public sealed class GatewaySessionTests
State = WorkerClientState.Faulted;
}
- ///
+ /// Increments the dispose count and completes asynchronously.
+ /// A completed value task.
public ValueTask DisposeAsync()
{
DisposeCount++;
@@ -259,16 +266,16 @@ public sealed class GatewaySessionTests
private sealed class FakeWorkerClient : IWorkerClient
{
- /// Gets the session identifier.
+ ///
public string SessionId { get; } = "session-test";
- /// Gets the worker process identifier.
+ ///
public int? ProcessId { get; } = 1234;
- /// Gets the worker client state.
+ ///
public WorkerClientState State { get; } = WorkerClientState.Ready;
- /// Gets the last recorded heartbeat timestamp.
+ ///
public DateTimeOffset LastHeartbeatAt { get; } = DateTimeOffset.UtcNow;
/// Gets the count of dispose invocations.
@@ -299,7 +306,8 @@ public sealed class GatewaySessionTests
{
}
- ///
+ /// Increments the dispose count and completes asynchronously.
+ /// A completed value task.
public ValueTask DisposeAsync()
{
DisposeCount++;
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionManagerBulkTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionManagerBulkTests.cs
index d5fd7d4..c5567bb 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionManagerBulkTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionManagerBulkTests.cs
@@ -21,6 +21,7 @@ namespace ZB.MOM.WW.MxGateway.Tests.Gateway.Sessions;
public sealed class SessionManagerBulkTests
{
/// Verifies that AddItemBulkAsync forwards the command and returns results.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AddItemBulkAsync_ForwardsOneAddItemBulkCommandAndReturnsResults()
{
@@ -50,6 +51,7 @@ public sealed class SessionManagerBulkTests
}
/// Verifies that AddItemBulkAsync propagates cancellation.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AddItemBulkAsync_PropagatesCancellation()
{
@@ -63,6 +65,7 @@ public sealed class SessionManagerBulkTests
}
/// Verifies that AdviseItemBulkAsync forwards the command and returns results.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AdviseItemBulkAsync_ForwardsOneAdviseItemBulkCommandAndReturnsResults()
{
@@ -90,6 +93,7 @@ public sealed class SessionManagerBulkTests
}
/// Verifies that AdviseItemBulkAsync propagates cancellation.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AdviseItemBulkAsync_PropagatesCancellation()
{
@@ -103,6 +107,7 @@ public sealed class SessionManagerBulkTests
}
/// Verifies that RemoveItemBulkAsync forwards the command and returns results.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RemoveItemBulkAsync_ForwardsOneRemoveItemBulkCommandAndReturnsResults()
{
@@ -128,6 +133,7 @@ public sealed class SessionManagerBulkTests
}
/// Verifies that RemoveItemBulkAsync propagates cancellation.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RemoveItemBulkAsync_PropagatesCancellation()
{
@@ -141,6 +147,7 @@ public sealed class SessionManagerBulkTests
}
/// Verifies that UnAdviseItemBulkAsync forwards the command and returns results.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task UnAdviseItemBulkAsync_ForwardsOneUnAdviseItemBulkCommandAndReturnsResults()
{
@@ -167,6 +174,7 @@ public sealed class SessionManagerBulkTests
}
/// Verifies that UnAdviseItemBulkAsync propagates cancellation.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task UnAdviseItemBulkAsync_PropagatesCancellation()
{
@@ -180,6 +188,7 @@ public sealed class SessionManagerBulkTests
}
/// Verifies that SubscribeBulkAsync surfaces per-entry failures.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SubscribeBulkAsync_SurfacesPerEntryFailures()
{
@@ -208,6 +217,7 @@ public sealed class SessionManagerBulkTests
}
/// Verifies that SubscribeBulkAsync propagates cancellation.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SubscribeBulkAsync_PropagatesCancellation()
{
@@ -221,6 +231,7 @@ public sealed class SessionManagerBulkTests
}
/// Verifies that UnsubscribeBulkAsync forwards the command and returns results.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task UnsubscribeBulkAsync_ForwardsOneUnsubscribeBulkCommandAndReturnsResults()
{
@@ -246,6 +257,7 @@ public sealed class SessionManagerBulkTests
}
/// Verifies that UnsubscribeBulkAsync propagates cancellation.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task UnsubscribeBulkAsync_PropagatesCancellation()
{
@@ -259,6 +271,7 @@ public sealed class SessionManagerBulkTests
}
/// Verifies that WriteBulkAsync surfaces per-entry failures.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WriteBulkAsync_SurfacesPerEntryFailures()
{
@@ -292,6 +305,7 @@ public sealed class SessionManagerBulkTests
}
/// Verifies that WriteBulkAsync propagates cancellation.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WriteBulkAsync_PropagatesCancellation()
{
@@ -308,6 +322,7 @@ public sealed class SessionManagerBulkTests
}
/// Verifies that Write2BulkAsync forwards the command and preserves timestamp payload.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Write2BulkAsync_ForwardsOneWrite2BulkCommandAndPreservesTimestampPayload()
{
@@ -351,6 +366,7 @@ public sealed class SessionManagerBulkTests
}
/// Verifies that Write2BulkAsync propagates cancellation.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Write2BulkAsync_PropagatesCancellation()
{
@@ -376,6 +392,7 @@ public sealed class SessionManagerBulkTests
}
/// Verifies that WriteSecuredBulkAsync forwards the command and preserves credential payload.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WriteSecuredBulkAsync_ForwardsOneWriteSecuredBulkCommandAndPreservesCredentialPayload()
{
@@ -427,6 +444,7 @@ public sealed class SessionManagerBulkTests
}
/// Verifies that WriteSecuredBulkAsync propagates cancellation.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WriteSecuredBulkAsync_PropagatesCancellation()
{
@@ -463,6 +481,7 @@ public sealed class SessionManagerBulkTests
/// client closing its stream would hit, which the pre-cancel pattern can't
/// exercise.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WriteSecuredBulkAsync_WhenCancelledMidFlight_ThrowsOperationCanceledForRequestToken()
{
@@ -499,6 +518,7 @@ public sealed class SessionManagerBulkTests
}
/// Verifies that WriteSecured2BulkAsync forwards the command and preserves credential and timestamp payload.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WriteSecured2BulkAsync_ForwardsOneWriteSecured2BulkCommandAndPreservesCredentialAndTimestampPayload()
{
@@ -547,6 +567,7 @@ public sealed class SessionManagerBulkTests
}
/// Verifies that WriteSecured2BulkAsync propagates cancellation.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WriteSecured2BulkAsync_PropagatesCancellation()
{
@@ -573,6 +594,7 @@ public sealed class SessionManagerBulkTests
}
/// Verifies that ReadBulkAsync surfaces per-entry failures.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadBulkAsync_SurfacesPerEntryFailures()
{
@@ -619,6 +641,7 @@ public sealed class SessionManagerBulkTests
}
/// Verifies that ReadBulkAsync propagates cancellation.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadBulkAsync_PropagatesCancellation()
{
@@ -779,7 +802,8 @@ public sealed class SessionManagerBulkTests
///
public void Kill(string reason) => State = WorkerClientState.Faulted;
- ///
+ /// Releases resources held by the fake worker client.
+ /// A completed value task.
public ValueTask DisposeAsync() => ValueTask.CompletedTask;
}
@@ -858,7 +882,8 @@ public sealed class SessionManagerBulkTests
_invokeCompletion.TrySetCanceled();
}
- ///
+ /// Cancels any pending invoke and releases resources held by this fake.
+ /// A completed value task.
public ValueTask DisposeAsync()
{
_invokeCompletion.TrySetCanceled();
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionManagerTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionManagerTests.cs
index 45134bf..de76279 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionManagerTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionManagerTests.cs
@@ -12,6 +12,7 @@ namespace ZB.MOM.WW.MxGateway.Tests.Gateway.Sessions;
public sealed class SessionManagerTests
{
/// Verifies that opening a session with a ready worker registers the session in ready state.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task OpenSessionAsync_WithWorkerReady_RegistersReadySession()
{
@@ -35,6 +36,7 @@ public sealed class SessionManagerTests
}
/// Verifies that opening a session sets the initial lease expiry from the configured default lease.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task OpenSessionAsync_SetsInitialDefaultLease()
{
@@ -51,6 +53,7 @@ public sealed class SessionManagerTests
}
/// Verifies that session generation creates client correlation ID from client name and session ID.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task OpenSessionAsync_GeneratesClientCorrelationIdFromClientNameAndSessionId()
{
@@ -67,6 +70,7 @@ public sealed class SessionManagerTests
}
/// Verifies that opening a session without a client session name uses the client correlation prefix.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task OpenSessionAsync_WhenClientSessionNameMissing_UsesClientCorrelationPrefix()
{
@@ -82,6 +86,7 @@ public sealed class SessionManagerTests
}
/// Verifies that invoking a command on a ready session forwards the command to the worker.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InvokeAsync_WhenSessionReady_ForwardsCommandToWorker()
{
@@ -99,6 +104,7 @@ public sealed class SessionManagerTests
}
/// Verifies that invoking a command on a ready session refreshes its lease expiry.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InvokeAsync_WhenSessionReady_RefreshesLease()
{
@@ -126,6 +132,7 @@ public sealed class SessionManagerTests
}
/// Verifies that gateway session subscribe bulk forwards one bulk command and returns results.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task GatewaySessionSubscribeBulkAsync_ForwardsOneBulkCommandAndReturnsResults()
{
@@ -171,6 +178,7 @@ public sealed class SessionManagerTests
}
/// Verifies that gateway session write bulk forwards one bulk command and returns results.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task GatewaySessionWriteBulkAsync_ForwardsOneBulkCommandAndReturnsResults()
{
@@ -236,6 +244,7 @@ public sealed class SessionManagerTests
}
/// Verifies that gateway session read bulk forwards one bulk command and returns results.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task GatewaySessionReadBulkAsync_ForwardsOneBulkCommandAndReturnsResults()
{
@@ -286,6 +295,7 @@ public sealed class SessionManagerTests
}
/// Verifies that invoking a command on a faulted session rejects the command.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InvokeAsync_WhenSessionFaulted_RejectsCommand()
{
@@ -311,6 +321,7 @@ public sealed class SessionManagerTests
/// producing a self-contradictory "Session ... is not ready. Current
/// state is Ready." message.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InvokeAsync_WhenWorkerNotReadyButSessionReady_DiagnosticIncludesBothStates()
{
@@ -335,6 +346,7 @@ public sealed class SessionManagerTests
}
/// Verifies that closing a session removes it from the registry.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CloseSessionAsync_RemovesClosedSession()
{
@@ -356,6 +368,7 @@ public sealed class SessionManagerTests
}
/// Verifies that closing a session kills the worker when shutdown fails.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CloseSessionAsync_WhenWorkerShutdownFails_KillsWorker()
{
@@ -377,6 +390,7 @@ public sealed class SessionManagerTests
}
/// Verifies that when worker shutdown fails, the session is removed and the slot is released.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CloseSessionAsync_WhenWorkerShutdownFails_RemovesSessionAndReleasesSlot()
{
@@ -423,6 +437,7 @@ public sealed class SessionManagerTests
}
/// Verifies that when the second close is canceled, the session is not removed if owned by the first close.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CloseSessionAsync_WhenSecondCloseIsCanceled_DoesNotRemoveSessionOwnedByFirstClose()
{
@@ -476,6 +491,7 @@ public sealed class SessionManagerTests
/// SessionManager.KillWorkerAsync → session.KillWorker(reason) →
/// IWorkerClient.Kill(reason).
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task KillWorkerAsync_KillsWorkerAndRemovesSession()
{
@@ -502,6 +518,7 @@ public sealed class SessionManagerTests
/// before any session lookup or worker call runs.
///
/// A blank or whitespace reason string.
+ /// A task that represents the asynchronous operation.
[Theory]
[InlineData("")]
[InlineData(" ")]
@@ -524,6 +541,7 @@ public sealed class SessionManagerTests
/// with cannot carry null for a
/// non-nullable string parameter on .NET 10, so the null case is its own fact.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task KillWorkerAsync_WithNullReason_ThrowsArgumentNullException()
{
@@ -539,6 +557,7 @@ public sealed class SessionManagerTests
}
/// Verifies that killing the worker for an unknown session raises SessionNotFound.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task KillWorkerAsync_WhenSessionMissing_ThrowsSessionNotFound()
{
@@ -555,6 +574,7 @@ public sealed class SessionManagerTests
/// decrement mxgateway.sessions.open (parity with the Server-006 fix in
/// OpenSessionAsync). Without the fix the gauge leaks one open session per failed kill.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task KillWorkerAsync_WhenSessionKillThrows_DecrementsOpenSessionGauge()
{
@@ -587,6 +607,7 @@ public sealed class SessionManagerTests
/// double-increment mxgateway.sessions.closed. The first kill wins, the second
/// observes wasClosed == true (or a missing session after removal) and short-circuits.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task KillWorkerAsync_ConcurrentCallsOnSameSession_CountClosedExactlyOnce()
{
@@ -627,6 +648,7 @@ public sealed class SessionManagerTests
/// the mxgateway.sessions.closed counter must increment. Without the fix, the
/// graceful-close failure path under-counts the closed counter.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ShutdownAsync_WhenSessionCloseThrows_StillDecrementsOpenSessionGaugeAndIncrementsClosedCounter()
{
@@ -655,6 +677,7 @@ public sealed class SessionManagerTests
}
/// Verifies that when worker creation fails, the session is removed from the registry.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task OpenSessionAsync_WhenWorkerCreationFails_RemovesSessionFromRegistry()
{
@@ -675,6 +698,7 @@ public sealed class SessionManagerTests
}
/// Verifies that closing expired leases only closes expired sessions.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CloseExpiredLeasesAsync_ClosesExpiredSessionsOnly()
{
@@ -698,6 +722,7 @@ public sealed class SessionManagerTests
}
/// Verifies that an expired-lease sweep leaves a session with an active event subscriber open.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CloseExpiredLeasesAsync_DoesNotCloseActiveEventSubscriber()
{
@@ -716,6 +741,7 @@ public sealed class SessionManagerTests
}
/// Verifies that shutdown closes all registered sessions.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ShutdownAsync_ClosesAllRegisteredSessions()
{
@@ -859,16 +885,16 @@ public sealed class SessionManagerTests
private sealed class FakeWorkerClient : IWorkerClient
{
- /// Gets the session ID for the fake worker client.
+ ///
public string SessionId { get; init; } = "session-1";
- /// Gets the process ID for the fake worker client.
+ ///
public int? ProcessId { get; init; } = 1234;
- /// Gets or sets the state of the fake worker client.
+ ///
public WorkerClientState State { get; set; } = WorkerClientState.Ready;
- /// Gets the last heartbeat timestamp for the fake worker client.
+ ///
public DateTimeOffset LastHeartbeatAt { get; init; } = DateTimeOffset.UtcNow;
/// Gets the number of times invoke was called on the fake worker client.
@@ -984,7 +1010,8 @@ public sealed class SessionManagerTests
State = WorkerClientState.Faulted;
}
- ///
+ /// Increments the dispose count and returns a completed task.
+ /// A completed value task.
public ValueTask DisposeAsync()
{
DisposeCount++;
@@ -992,6 +1019,7 @@ public sealed class SessionManagerTests
}
/// Waits for shutdown to start on the fake worker client.
+ /// A task that resolves once shutdown has started.
public Task WaitForShutdownStartAsync()
{
return ShutdownStarted.Task.WaitAsync(TimeSpan.FromSeconds(5));
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionWorkerClientFactoryFakeWorkerTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionWorkerClientFactoryFakeWorkerTests.cs
index a61cb96..1f76d14 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionWorkerClientFactoryFakeWorkerTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionWorkerClientFactoryFakeWorkerTests.cs
@@ -20,6 +20,7 @@ public sealed class SessionWorkerClientFactoryFakeWorkerTests : IAsyncDisposable
/// Awaits every scripted worker task so an unhandled exception fails the owning test
/// instead of surfacing later as an unobserved .
///
+ /// A task that represents the asynchronous dispose operation.
public async ValueTask DisposeAsync()
{
foreach (IWorkerTaskLauncher launcher in _launchers)
@@ -29,6 +30,7 @@ public sealed class SessionWorkerClientFactoryFakeWorkerTests : IAsyncDisposable
}
/// Verifies that the factory creates a ready worker client with a scripted fake worker process.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CreateAsync_WithScriptedFakeWorker_ReturnsReadyClient()
{
@@ -62,6 +64,7 @@ public sealed class SessionWorkerClientFactoryFakeWorkerTests : IAsyncDisposable
}
/// Verifies that a failed fake worker startup throws a worker client exception.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CreateAsync_WhenFakeWorkerStartupFails_ThrowsWorkerClientException()
{
@@ -82,6 +85,7 @@ public sealed class SessionWorkerClientFactoryFakeWorkerTests : IAsyncDisposable
}
/// Verifies that a worker that never sends ready times out and is killed.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CreateAsync_WhenFakeWorkerNeverSendsReady_TimesOutAndKillsWorker()
{
@@ -167,6 +171,7 @@ public sealed class SessionWorkerClientFactoryFakeWorkerTests : IAsyncDisposable
/// teardown faults expected when the worker client kills or disposes the worker.
///
/// Maximum time to wait for the worker task.
+ /// A task that represents the asynchronous operation.
Task ObserveWorkerTaskAsync(TimeSpan timeout);
}
@@ -348,10 +353,10 @@ public sealed class SessionWorkerClientFactoryFakeWorkerTests : IAsyncDisposable
///
public int Id { get; } = processId;
- /// Gets a value indicating whether the process has exited.
+ ///
public bool HasExited { get; private set; }
- /// Gets the process exit code, or null if the process has not exited.
+ ///
public int? ExitCode { get; private set; }
/// Gets the number of times the Kill method was called.
@@ -370,7 +375,7 @@ public sealed class SessionWorkerClientFactoryFakeWorkerTests : IAsyncDisposable
MarkExited(-1);
}
- ///
+ /// Marks this fake process as disposed.
public void Dispose()
{
_disposed = true;
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/FakeWorkerHarnessTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/FakeWorkerHarnessTests.cs
index a4edd57..020c231 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/FakeWorkerHarnessTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/FakeWorkerHarnessTests.cs
@@ -11,6 +11,7 @@ public sealed class FakeWorkerHarnessTests
private static readonly TimeSpan TestTimeout = TimeSpan.FromSeconds(5);
/// Verifies that completing startup with hello and ready transitions the client to ready state.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CompleteStartupAsync_WithHelloAndReady_TransitionsClientToReady()
{
@@ -28,6 +29,7 @@ public sealed class FakeWorkerHarnessTests
}
/// Verifies that a protocol version mismatch during startup fails the client.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task StartAsync_WithProtocolMismatch_FailsStartup()
{
@@ -47,6 +49,7 @@ public sealed class FakeWorkerHarnessTests
}
/// Verifies that a scripted reply completes a pending command invocation.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InvokeAsync_WithScriptedReply_CompletesCommand()
{
@@ -69,6 +72,7 @@ public sealed class FakeWorkerHarnessTests
}
/// Verifies that scripted events are yielded in order through the event stream.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadEventsAsync_WithScriptedEvents_YieldsOrderedEvents()
{
@@ -93,6 +97,7 @@ public sealed class FakeWorkerHarnessTests
}
/// Verifies that a scripted fault from the worker faults the client.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadLoop_WithScriptedFault_FaultsClient()
{
@@ -116,6 +121,7 @@ public sealed class FakeWorkerHarnessTests
/// so the timestamp advance is deterministic rather
/// than relying on a wall-clock Task.Delay exceeding clock resolution.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SendHeartbeatAsync_UpdatesClientHeartbeatState()
{
@@ -138,6 +144,7 @@ public sealed class FakeWorkerHarnessTests
}
/// Verifies that a hung worker times out pending command invocations.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InvokeAsync_WithHungWorker_TimesOutPendingCommand()
{
@@ -159,6 +166,7 @@ public sealed class FakeWorkerHarnessTests
}
/// Verifies that a malformed frame in the read loop faults the client.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadLoop_WithMalformedFrame_FaultsClient()
{
@@ -176,6 +184,7 @@ public sealed class FakeWorkerHarnessTests
}
/// Verifies that a shutdown acknowledgment from the worker closes the client.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ShutdownAsync_WithShutdownAck_ClosesClient()
{
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/Fakes/FakeWorkerHarness.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/Fakes/FakeWorkerHarness.cs
index 9d03b6d..52f8802 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/Fakes/FakeWorkerHarness.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/Fakes/FakeWorkerHarness.cs
@@ -52,6 +52,7 @@ public sealed class FakeWorkerHarness : IAsyncDisposable
/// Protocol version for frame communication.
/// Maximum message size in bytes.
/// Token to cancel the asynchronous operation.
+ /// A task that resolves to a connected instance.
public static async Task CreateConnectedPairAsync(
string sessionId = DefaultSessionId,
string nonce = DefaultNonce,
@@ -87,6 +88,7 @@ public sealed class FakeWorkerHarness : IAsyncDisposable
/// Protocol version for frame communication.
/// Maximum message size in bytes.
/// Token to cancel the asynchronous operation.
+ /// A task that resolves to a connected instance.
public static async Task ConnectToGatewayPipeAsync(
string sessionId,
string nonce,
@@ -205,6 +207,7 @@ public sealed class FakeWorkerHarness : IAsyncDisposable
/// Protocol version override.
/// Nonce override.
/// Token to cancel the asynchronous operation.
+ /// A task that represents the asynchronous operation.
public async Task SendWorkerHelloAsync(
int workerProcessId = DefaultWorkerProcessId,
string workerVersion = "fake-worker",
@@ -230,6 +233,7 @@ public sealed class FakeWorkerHarness : IAsyncDisposable
/// MXAccess COM ProgID.
/// MXAccess COM CLSID.
/// Token to cancel the asynchronous operation.
+ /// A task that represents the asynchronous operation.
public async Task SendWorkerReadyAsync(
int workerProcessId = DefaultWorkerProcessId,
string mxaccessProgid = "LMXProxy.LMXProxyServer.1",
@@ -255,6 +259,7 @@ public sealed class FakeWorkerHarness : IAsyncDisposable
/// Human-readable status message.
/// Optional callback to customize the reply.
/// Token to cancel the asynchronous operation.
+ /// A task that represents the asynchronous operation.
public async Task ReplyToCommandAsync(
WorkerEnvelope commandEnvelope,
ProtocolStatusCode statusCode = ProtocolStatusCode.Ok,
@@ -296,6 +301,7 @@ public sealed class FakeWorkerHarness : IAsyncDisposable
/// Family of the event to emit.
/// Token to cancel the asynchronous operation.
/// Optional callback to customize the event.
+ /// A task that represents the asynchronous operation.
public async Task EmitEventAsync(
MxEventFamily family,
CancellationToken cancellationToken = default,
@@ -325,6 +331,7 @@ public sealed class FakeWorkerHarness : IAsyncDisposable
/// Category of the fault.
/// Diagnostic message describing the fault.
/// Token to cancel the asynchronous operation.
+ /// A task that represents the asynchronous operation.
public async Task EmitFaultAsync(
WorkerFaultCategory category,
string diagnosticMessage,
@@ -350,6 +357,7 @@ public sealed class FakeWorkerHarness : IAsyncDisposable
/// Current worker state.
/// Token to cancel the asynchronous operation.
/// Optional callback to customize the heartbeat.
+ /// A task that represents the asynchronous operation.
public async Task SendHeartbeatAsync(
WorkerState state = WorkerState.Ready,
CancellationToken cancellationToken = default,
@@ -373,6 +381,7 @@ public sealed class FakeWorkerHarness : IAsyncDisposable
/// Sends a shutdown acknowledgment message to the gateway.
/// Protocol status code for the acknowledgment.
/// Token to cancel the asynchronous operation.
+ /// A task that represents the asynchronous operation.
public async Task SendShutdownAckAsync(
ProtocolStatusCode statusCode = ProtocolStatusCode.Ok,
CancellationToken cancellationToken = default)
@@ -394,6 +403,7 @@ public sealed class FakeWorkerHarness : IAsyncDisposable
/// Writes a malformed payload directly to the worker stream.
/// Malformed payload bytes to write.
/// Token to cancel the asynchronous operation.
+ /// A task that represents the asynchronous operation.
public async Task WriteMalformedPayloadAsync(
ReadOnlyMemory payload,
CancellationToken cancellationToken = default)
@@ -412,6 +422,7 @@ public sealed class FakeWorkerHarness : IAsyncDisposable
/// Writes an oversized frame header to the worker stream for testing frame size limits.
/// Length of the oversized payload in bytes.
/// Token to cancel the asynchronous operation.
+ /// A task that represents the asynchronous operation.
public async Task WriteOversizedFrameHeaderAsync(
uint payloadLength,
CancellationToken cancellationToken = default)
@@ -430,6 +441,7 @@ public sealed class FakeWorkerHarness : IAsyncDisposable
}
/// Disposes the worker-side stream.
+ /// A value task that represents the asynchronous operation.
public async ValueTask DisposeWorkerSideAsync()
{
if (_workerSideDisposed)
@@ -441,7 +453,8 @@ public sealed class FakeWorkerHarness : IAsyncDisposable
_workerSideDisposed = true;
}
- ///
+ /// Disposes both the worker-side and gateway-side streams.
+ /// A value task that represents the asynchronous operation.
public async ValueTask DisposeAsync()
{
await DisposeWorkerSideAsync().ConfigureAwait(false);
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/OrphanWorkerTerminatorTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/OrphanWorkerTerminatorTests.cs
index 3f407a7..8670b37 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/OrphanWorkerTerminatorTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/OrphanWorkerTerminatorTests.cs
@@ -129,12 +129,10 @@ public sealed class OrphanWorkerTerminatorTests
/// Gets or sets the process ID that should throw when killed.
public int? ThrowOnKillProcessId { get; init; }
- /// Gets the list of running processes by name.
- /// The process name to search for.
+ ///
public IReadOnlyList GetProcessesByName(string processName) => processes;
- /// Kills the specified process or records the kill attempt.
- /// The process identifier to kill.
+ ///
public void Kill(int processId)
{
if (ThrowOnKillProcessId == processId)
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerClientTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerClientTests.cs
index 7d46680..da10949 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerClientTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerClientTests.cs
@@ -16,6 +16,7 @@ public sealed class WorkerClientTests
private static readonly TimeSpan TestTimeout = TimeSpan.FromSeconds(5);
/// Verifies that StartAsync enters ready state after receiving worker hello and ready messages.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task StartAsync_WithWorkerHelloAndReady_EntersReadyState()
{
@@ -29,6 +30,7 @@ public sealed class WorkerClientTests
}
/// Verifies that InvokeAsync completes a pending command when a matching reply arrives.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InvokeAsync_WithMatchingReply_CompletesPendingCommand()
{
@@ -55,6 +57,7 @@ public sealed class WorkerClientTests
}
/// Verifies that InvokeAsync ignores late replies and keeps the client ready.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InvokeAsync_WithLateReply_IgnoresLateReplyAndKeepsClientReady()
{
@@ -93,6 +96,7 @@ public sealed class WorkerClientTests
}
/// Verifies that ReadEventsAsync yields events in pipe order from the worker.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadEventsAsync_WithWorkerEvents_YieldsEventsInPipeOrder()
{
@@ -119,6 +123,7 @@ public sealed class WorkerClientTests
}
/// Verifies that the read loop faults the client when the event queue overflows.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadLoop_WhenEventQueueOverflows_FaultsClient()
{
@@ -154,6 +159,7 @@ public sealed class WorkerClientTests
/// Faulted state before it calls KillOwnedProcess, so a state-based
/// wait can observe Faulted while KillCount is still 0.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadLoop_WhenClientFaults_KillsOwnedWorkerProcess()
{
@@ -192,6 +198,7 @@ public sealed class WorkerClientTests
/// invoke task with a carrying the
/// pipe-disconnected error code rather than hanging until the command timeout.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InvokeAsync_WhenPipeDisconnectsMidCommand_FailsPendingInvokeWithPipeDisconnected()
{
@@ -223,6 +230,7 @@ public sealed class WorkerClientTests
/// task with a carrying the worker-faulted
/// error code.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InvokeAsync_WhenWorkerFaultsMidCommand_FailsPendingInvokeWithWorkerFaulted()
{
@@ -248,6 +256,7 @@ public sealed class WorkerClientTests
}
/// Verifies that pipe disconnect faults the client.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadLoop_WhenPipeDisconnects_FaultsClient()
{
@@ -265,6 +274,7 @@ public sealed class WorkerClientTests
}
/// Verifies that the read loop stops the running worker metric when the pipe disconnects.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadLoop_WhenPipeDisconnects_StopsRunningWorkerMetric()
{
@@ -288,6 +298,7 @@ public sealed class WorkerClientTests
}
/// Verifies that DisposeAsync returns within a bounded timeout when the pipe read is blocked.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DisposeAsync_WhenPipeReadIsBlocked_ReturnsWithinBoundedTimeout()
{
@@ -304,7 +315,8 @@ public sealed class WorkerClientTests
$"DisposeAsync took {elapsed.TotalMilliseconds:N0}ms.");
}
- /// Verifies that the read loop updates the last heartbeat and worker process when a heartbeat arrives.
+ /// Verifies that DisposeAsync kills the owned worker process before disposing.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DisposeAsync_WhenOwnedWorkerStillRuns_KillsProcessBeforeDisposing()
{
@@ -325,6 +337,7 @@ public sealed class WorkerClientTests
/// deterministic instead of relying on a wall-clock Task.Delay exceeding
/// resolution.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadLoop_WhenHeartbeatArrives_UpdatesLastHeartbeatAndWorkerProcess()
{
@@ -352,6 +365,7 @@ public sealed class WorkerClientTests
/// timer stays on the real clock and
/// observes the manually-advanced grace on its next tick.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task HeartbeatMonitor_WhenHeartbeatExpires_FaultsClient()
{
@@ -385,6 +399,7 @@ public sealed class WorkerClientTests
/// gap is more likely caused by pipe-write contention than by a hung
/// worker. Mirrors Worker-023 on the worker side.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task HeartbeatMonitor_WhenCommandInFlightWithinCeiling_DoesNotFaultOnExpiredHeartbeat()
{
@@ -427,6 +442,7 @@ public sealed class WorkerClientTests
/// heartbeat watchdog fires anyway — a truly stuck COM call shouldn't
/// keep the watchdog suppressed indefinitely.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task HeartbeatMonitor_WhenPendingCommandExceedsStuckCeiling_FaultsClient()
{
@@ -471,6 +487,7 @@ public sealed class WorkerClientTests
/// and the diagnostic must name the channel capacity, depth, and
/// actionable remediation.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task EnqueueWorkerEvent_WhenChannelFullPastTimeout_FaultsWithRichDiagnostic()
{
@@ -722,6 +739,7 @@ public sealed class WorkerClientTests
public WorkerFrameWriter WorkerWriter { get; }
/// Creates a connected pipe pair for testing.
+ /// A task that resolves to the connected pipe pair.
public static async Task CreateAsync()
{
string pipeName = $"mxaccessgw-workerclient-tests-{Guid.NewGuid():N}";
@@ -745,6 +763,7 @@ public sealed class WorkerClientTests
}
/// Disposes the worker side of the pipe.
+ /// A task that represents the asynchronous operation.
public async ValueTask DisposeWorkerSideAsync()
{
if (_workerSideDisposed)
@@ -757,6 +776,7 @@ public sealed class WorkerClientTests
}
/// Disposes the duplex stream.
+ /// A task that represents the asynchronous operation.
public async ValueTask DisposeAsync()
{
await DisposeWorkerSideAsync();
@@ -768,13 +788,13 @@ public sealed class WorkerClientTests
{
private readonly TaskCompletionSource _exited = new(TaskCreationOptions.RunContinuationsAsynchronously);
- /// Gets the process ID.
+ ///
public int Id { get; } = WorkerProcessId;
- /// Gets a value indicating whether the process has exited.
+ ///
public bool HasExited { get; private set; }
- /// Gets the process exit code.
+ ///
public int? ExitCode { get; private set; }
/// Gets the number of times kill was called.
@@ -792,8 +812,7 @@ public sealed class WorkerClientTests
return new ValueTask(_exited.Task.WaitAsync(cancellationToken));
}
- /// Records a kill request.
- /// Whether to kill the entire process tree.
+ ///
public void Kill(bool entireProcessTree)
{
KillCount++;
@@ -803,7 +822,7 @@ public sealed class WorkerClientTests
_exited.TrySetResult();
}
- ///
+ /// Marks the process as disposed.
public void Dispose()
{
Disposed = true;
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerExecutableValidatorTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerExecutableValidatorTests.cs
index 6f94e73..29f816d 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerExecutableValidatorTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerExecutableValidatorTests.cs
@@ -129,7 +129,7 @@ public sealed class WorkerExecutableValidatorTests : IDisposable
return path;
}
- ///
+ /// Deletes all temporary PE fixture files created during the test.
public void Dispose()
{
foreach (string path in _tempFiles)
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerFrameProtocolTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerFrameProtocolTests.cs
index 6696ac6..ed26f6d 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerFrameProtocolTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerFrameProtocolTests.cs
@@ -11,6 +11,7 @@ public sealed class WorkerFrameProtocolTests
private const string SessionId = "session-1";
/// Verifies that writing and reading a valid envelope round-trips the frame correctly.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WriteAndReadAsync_WithValidEnvelope_RoundTripsFrame()
{
@@ -29,6 +30,7 @@ public sealed class WorkerFrameProtocolTests
}
/// Verifies that reading a frame with partial reads reassembles the frame correctly.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadAsync_WithPartialReads_ReassemblesFrame()
{
@@ -45,6 +47,7 @@ public sealed class WorkerFrameProtocolTests
}
/// Verifies that reading a frame with zero length throws a malformed length exception.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadAsync_WithZeroLengthFrame_ThrowsMalformedLength()
{
@@ -60,6 +63,7 @@ public sealed class WorkerFrameProtocolTests
}
/// Verifies that reading a frame with oversized length throws before allocating the payload.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadAsync_WithOversizedLength_ThrowsBeforePayloadAllocation()
{
@@ -77,6 +81,7 @@ public sealed class WorkerFrameProtocolTests
}
/// Verifies that reading a frame with wrong protocol version throws a protocol version mismatch exception.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadAsync_WithWrongProtocolVersion_ThrowsProtocolVersionMismatch()
{
@@ -94,6 +99,7 @@ public sealed class WorkerFrameProtocolTests
}
/// Verifies that reading a frame with wrong session ID throws a session mismatch exception.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadAsync_WithWrongSessionId_ThrowsSessionMismatch()
{
@@ -111,6 +117,7 @@ public sealed class WorkerFrameProtocolTests
}
/// Verifies that reading a frame with malformed payload throws an invalid envelope exception.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadAsync_WithMalformedPayload_ThrowsInvalidEnvelope()
{
@@ -127,6 +134,7 @@ public sealed class WorkerFrameProtocolTests
}
/// Verifies that reading a frame with missing envelope body throws an invalid envelope exception.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadAsync_WithMissingEnvelopeBody_ThrowsInvalidEnvelope()
{
@@ -144,6 +152,7 @@ public sealed class WorkerFrameProtocolTests
}
/// Verifies that writing an oversized envelope throws a message too large exception.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WriteAsync_WithOversizedEnvelope_ThrowsMessageTooLarge()
{
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerProcessLauncherTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerProcessLauncherTests.cs
index f8f93a5..5fd6bac 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerProcessLauncherTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Workers/WorkerProcessLauncherTests.cs
@@ -14,6 +14,7 @@ public sealed class WorkerProcessLauncherTests
private const string Nonce = "super-secret-nonce";
/// Verifies that a valid worker executable starts with correct bootstrap arguments and nonce environment variable.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task LaunchAsync_WithValidWorker_StartsProcessWithBootstrapArgumentsAndNonceEnvironment()
{
@@ -48,6 +49,7 @@ public sealed class WorkerProcessLauncherTests
}
/// Verifies that a failed startup probe kills and disposes the worker process.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task LaunchAsync_WhenStartupProbeFails_KillsAndDisposesWorker()
{
@@ -74,6 +76,7 @@ public sealed class WorkerProcessLauncherTests
}
/// Verifies that transient startup probe failures are retried without respawning the worker process.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task LaunchAsync_WhenStartupProbeFailsTransiently_RetriesWithoutRespawningWorker()
{
@@ -101,6 +104,7 @@ public sealed class WorkerProcessLauncherTests
}
/// Verifies that a startup probe timeout kills and disposes the worker process.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task LaunchAsync_WhenStartupTimesOut_KillsAndDisposesWorker()
{
@@ -126,6 +130,7 @@ public sealed class WorkerProcessLauncherTests
}
/// Verifies that a missing worker executable fails before attempting to start the process.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task LaunchAsync_WhenExecutableDoesNotExist_FailsBeforeStartingProcess()
{
@@ -143,6 +148,7 @@ public sealed class WorkerProcessLauncherTests
}
/// Verifies that a worker executable with mismatched architecture fails before attempting to start.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task LaunchAsync_WhenExecutableArchitectureDoesNotMatch_FailsBeforeStartingProcess()
{
@@ -160,6 +166,7 @@ public sealed class WorkerProcessLauncherTests
}
/// Verifies that a worker that has already exited fails and disposes without additional killing.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task LaunchAsync_WhenWorkerAlreadyExited_FailsAndDisposesWorkerWithoutKill()
{
@@ -246,10 +253,10 @@ public sealed class WorkerProcessLauncherTests
///
public int Id { get; } = processId;
- /// Gets or sets a value indicating whether the process has exited.
+ ///
public bool HasExited { get; set; }
- /// Gets or sets the process exit code.
+ ///
public int? ExitCode { get; set; }
/// Gets a value indicating whether the Dispose method was called.
@@ -272,7 +279,7 @@ public sealed class WorkerProcessLauncherTests
HasExited = true;
}
- ///
+ /// Records that the fake process was disposed.
public void Dispose()
{
DisposeCalled = true;
@@ -344,7 +351,7 @@ public sealed class WorkerProcessLauncherTests
/// Gets a value indicating whether the Dispose method was called.
public bool DisposeCalled { get; private set; }
- ///
+ /// Records that the pipe reservation was disposed.
public void Dispose()
{
DisposeCalled = true;
@@ -363,6 +370,7 @@ public sealed class WorkerProcessLauncherTests
public string Path { get; }
/// Creates a new temporary directory for testing.
+ /// A new backed by a freshly created temp directory.
public static TestDirectory Create()
{
string path = System.IO.Path.Combine(System.IO.Path.GetTempPath(), $"mxgateway-tests-{Guid.NewGuid():N}");
@@ -391,7 +399,7 @@ public sealed class WorkerProcessLauncherTests
return path;
}
- ///
+ /// Deletes the temporary directory and all its contents.
public void Dispose()
{
Directory.Delete(Path, recursive: true);
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Security/Audit/CanonicalAuditStoreAndAdapterTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Security/Audit/CanonicalAuditStoreAndAdapterTests.cs
index 2eefb63..240e50c 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Security/Audit/CanonicalAuditStoreAndAdapterTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Security/Audit/CanonicalAuditStoreAndAdapterTests.cs
@@ -21,6 +21,7 @@ public sealed class CanonicalAuditStoreAndAdapterTests : IDisposable
private readonly List _tempDirectories = [];
/// A canonical event with all fields populated round-trips through the store.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Store_InsertThenListRecent_RoundTripsAllFields()
{
@@ -61,6 +62,7 @@ public sealed class CanonicalAuditStoreAndAdapterTests : IDisposable
}
/// Nullable canonical fields round-trip as null, not empty string.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Store_InsertWithNullOptionalFields_RoundTripsAsNull()
{
@@ -86,6 +88,7 @@ public sealed class CanonicalAuditStoreAndAdapterTests : IDisposable
}
/// ListRecent returns newest-first.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Store_ListRecent_ReturnsNewestFirst()
{
@@ -100,6 +103,7 @@ public sealed class CanonicalAuditStoreAndAdapterTests : IDisposable
}
/// The writer is best-effort: a faulting store does not surface to the caller.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Writer_WhenStoreFails_DoesNotThrow()
{
@@ -123,6 +127,7 @@ public sealed class CanonicalAuditStoreAndAdapterTests : IDisposable
/// A library event with a KeyId maps to a canonical Success event under category ApiKey,
/// and the adapter maps it back to the original entry for the dashboard view.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Adapter_KeyedEvent_RoundTripsThroughCanonicalStore()
{
@@ -158,6 +163,7 @@ public sealed class CanonicalAuditStoreAndAdapterTests : IDisposable
}
/// The keyless library init-db event maps to Actor "system" and back to a null KeyId.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Adapter_InitDbKeylessEvent_MapsToSystemActor()
{
@@ -184,6 +190,7 @@ public sealed class CanonicalAuditStoreAndAdapterTests : IDisposable
}
/// Any other keyless library event maps to Actor "cli" and back to a null KeyId.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Adapter_OtherKeylessEvent_MapsToCliActor()
{
@@ -207,6 +214,7 @@ public sealed class CanonicalAuditStoreAndAdapterTests : IDisposable
}
/// A constraint-denied library event maps to Outcome.Denied.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Adapter_ConstraintDeniedEvent_MapsToDeniedOutcome()
{
@@ -234,6 +242,7 @@ public sealed class CanonicalAuditStoreAndAdapterTests : IDisposable
/// The adapter does NOT throw when the underlying write fails (it forwards through the
/// best-effort writer), preserving the IApiKeyAuditStore caller's flow.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Adapter_WhenWriterFails_DoesNotThrow()
{
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/ApiKeyAdminCliRunnerTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/ApiKeyAdminCliRunnerTests.cs
index c6cce0f..e95d5cc 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/ApiKeyAdminCliRunnerTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/ApiKeyAdminCliRunnerTests.cs
@@ -14,6 +14,7 @@ public sealed class ApiKeyAdminCliRunnerTests : IDisposable
{
private readonly List _tempDirectories = [];
/// Verifies that CreateKeyAsync creates an authenticating key and audits the action.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CreateKeyAsync_CreatesAuthenticatingKeyAndAudits()
{
@@ -52,6 +53,7 @@ public sealed class ApiKeyAdminCliRunnerTests : IDisposable
}
/// Verifies that ListKeysAsync does not print the raw secret.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ListKeysAsync_DoesNotPrintRawSecret()
{
@@ -82,6 +84,7 @@ public sealed class ApiKeyAdminCliRunnerTests : IDisposable
}
/// Verifies that RevokeKeyAsync causes the revoked key to fail verification and is audited.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RevokeKeyAsync_RevokedKeyFailsVerificationAndAudits()
{
@@ -117,6 +120,7 @@ public sealed class ApiKeyAdminCliRunnerTests : IDisposable
}
/// Verifies that RotateKeyAsync prints the new secret once and invalidates the old secret.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RotateKeyAsync_PrintsNewSecretOnceAndInvalidatesOldSecret()
{
@@ -154,6 +158,7 @@ public sealed class ApiKeyAdminCliRunnerTests : IDisposable
}
/// Verifies that CreateKeyAsync prints the raw secret exactly once.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CreateKeyAsync_PrintsRawSecretExactlyOnce()
{
@@ -182,6 +187,7 @@ public sealed class ApiKeyAdminCliRunnerTests : IDisposable
}
/// Verifies that API key constraints are persisted correctly.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CreateKeyAsync_WithConstraints_PersistsConstraints()
{
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/ApiKeyVerifierTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/ApiKeyVerifierTests.cs
index 5fa6f0e..6d8f8c5 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/ApiKeyVerifierTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/ApiKeyVerifierTests.cs
@@ -18,6 +18,7 @@ public sealed class ApiKeyVerifierTests
private static readonly ApiKeyOptions Options = new() { TokenPrefix = "mxgw" };
/// Verifies that VerifyAsync returns identity and scopes for a valid key.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task VerifyAsync_ValidKey_ReturnsIdentityAndScopes()
{
@@ -38,6 +39,7 @@ public sealed class ApiKeyVerifierTests
}
/// Verifies that VerifyAsync does not expose the raw secret in the result.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task VerifyAsync_ValidKey_DoesNotExposeRawSecretInResult()
{
@@ -55,6 +57,7 @@ public sealed class ApiKeyVerifierTests
/// Verifies that VerifyAsync fails as missing/malformed for a malformed key.
/// Authorization header value to test.
+ /// A task that represents the asynchronous operation.
[Theory]
[InlineData("")]
[InlineData("Bearer mxgw_operator01")]
@@ -72,6 +75,7 @@ public sealed class ApiKeyVerifierTests
}
/// Verifies that VerifyAsync fails for an unknown key.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task VerifyAsync_UnknownKey_Fails()
{
@@ -86,6 +90,7 @@ public sealed class ApiKeyVerifierTests
}
/// Verifies that VerifyAsync fails for a wrong secret (constant-time compare rejects it).
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task VerifyAsync_WrongSecret_Fails()
{
@@ -102,6 +107,7 @@ public sealed class ApiKeyVerifierTests
}
/// Verifies that VerifyAsync fails for a revoked key.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task VerifyAsync_RevokedKey_Fails()
{
@@ -118,6 +124,7 @@ public sealed class ApiKeyVerifierTests
}
/// Verifies that VerifyAsync fails closed when the pepper is missing.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task VerifyAsync_MissingPepper_Fails()
{
@@ -160,6 +167,7 @@ public sealed class ApiKeyVerifierTests
private sealed class FakePepperProvider(string? pepper) : IApiKeyPepperProvider
{
/// Returns the configured pepper (or null to simulate an unavailable pepper).
+ /// The pepper string, or null if unavailable.
public string? GetPepper() => pepper;
}
@@ -169,13 +177,19 @@ public sealed class ApiKeyVerifierTests
/// Gets whether the key was marked as used.
public bool MarkedUsed { get; private set; }
- ///
+ /// Returns the stored key record if the key ID matches; otherwise null.
+ /// The key ID to look up.
+ /// Cancellation token.
+ /// A task that resolves to the matching key record, or null if not found.
public Task FindByKeyIdAsync(string keyId, CancellationToken ct)
{
return Task.FromResult(storedKey?.KeyId == keyId ? storedKey : null);
}
- ///
+ /// Returns the stored key record if the key ID matches and the key is not revoked; otherwise null.
+ /// The key ID to look up.
+ /// Cancellation token.
+ /// A task that resolves to the active key record, or null if not found or revoked.
public Task FindActiveByKeyIdAsync(string keyId, CancellationToken ct)
{
return Task.FromResult(
@@ -184,7 +198,11 @@ public sealed class ApiKeyVerifierTests
: null);
}
- ///
+ /// Records that the key was used.
+ /// The key ID to mark as used.
+ /// The timestamp of use.
+ /// Cancellation token.
+ /// A task that represents the asynchronous operation.
public Task MarkUsedAsync(string keyId, DateTimeOffset whenUtc, CancellationToken ct)
{
MarkedUsed = storedKey?.KeyId == keyId;
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/SqliteAuthStoreTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/SqliteAuthStoreTests.cs
index 8b6b633..9e7fb7b 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/SqliteAuthStoreTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/SqliteAuthStoreTests.cs
@@ -23,6 +23,7 @@ public sealed class SqliteAuthStoreTests : IDisposable
///
/// Verifies that MigrateAsync initializes the database schema at the donor's version (2).
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task MigrateAsync_EmptyDatabase_InitializesCurrentSchema()
{
@@ -41,6 +42,7 @@ public sealed class SqliteAuthStoreTests : IDisposable
///
/// Verifies that MigrateAsync migrates and is idempotent.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task MigrateAsync_ExistingVersionZeroDatabase_MigratesIdempotently()
{
@@ -61,6 +63,7 @@ public sealed class SqliteAuthStoreTests : IDisposable
///
/// Verifies that gateway startup fails with a newer schema version.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task StartAsync_NewerSchemaVersion_BlocksStartup()
{
@@ -83,6 +86,7 @@ public sealed class SqliteAuthStoreTests : IDisposable
/// Verifies that FindActiveByKeyIdAsync returns an active key, reading a row whose columns match
/// the donor schema (peppered secret_hash BLOB, ordinal-sorted scopes JSON).
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task FindActiveByKeyIdAsync_ExistingActiveKey_ReturnsKey()
{
@@ -106,6 +110,7 @@ public sealed class SqliteAuthStoreTests : IDisposable
///
/// Verifies that FindActiveByKeyIdAsync returns null for a revoked key.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task FindActiveByKeyIdAsync_RevokedKey_ReturnsNull()
{
@@ -129,6 +134,7 @@ public sealed class SqliteAuthStoreTests : IDisposable
///
/// Verifies that the audit store persists audit events.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ApiKeyAuditStore_AppendAsync_PersistsAuditEvent()
{
@@ -163,6 +169,7 @@ public sealed class SqliteAuthStoreTests : IDisposable
/// the auth database in WAL journal mode so concurrent readers and writers degrade
/// gracefully instead of surfacing SQLITE_BUSY on the request path.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task OpenConnectionAsync_EnablesWalJournalModeAndBusyTimeout()
{
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/TempDatabaseDirectory.cs b/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/TempDatabaseDirectory.cs
index ff97cab..96cff32 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/TempDatabaseDirectory.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Security/Authentication/TempDatabaseDirectory.cs
@@ -22,6 +22,7 @@ internal sealed class TempDatabaseDirectory : IDisposable
/// Creates a new uniquely named temporary directory under the given prefix.
/// Folder name placed under %TEMP% to group related test directories.
+ /// A new wrapping the created path.
public static TempDatabaseDirectory Create(string prefix)
{
string path = System.IO.Path.Combine(
@@ -35,12 +36,13 @@ internal sealed class TempDatabaseDirectory : IDisposable
/// Returns a database file path inside this temporary directory.
/// Database file name; defaults to the gateway auth database name.
+ /// The full path to the named file inside this directory.
public string DatabasePath(string fileName = "gateway-auth.db")
{
return System.IO.Path.Combine(Path, fileName);
}
- ///
+ /// Clears SQLite connection pools and deletes the temporary directory.
public void Dispose()
{
if (_disposed)
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Security/Authorization/ConstraintEnforcerTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Security/Authorization/ConstraintEnforcerTests.cs
index 379ce2d..7982525 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Security/Authorization/ConstraintEnforcerTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Security/Authorization/ConstraintEnforcerTests.cs
@@ -16,6 +16,7 @@ namespace ZB.MOM.WW.MxGateway.Tests.Security.Authorization;
public sealed class ConstraintEnforcerTests
{
/// Verifies that read outside allowed subtree returns failure.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CheckReadTagAsync_WhenOutsideReadSubtree_ReturnsFailure()
{
@@ -35,6 +36,7 @@ public sealed class ConstraintEnforcerTests
}
/// Verifies that write with high classification returns failure and audits.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CheckWriteHandleAsync_WhenClassificationTooHigh_ReturnsFailureAndAudits()
{
@@ -84,6 +86,7 @@ public sealed class ConstraintEnforcerTests
}
/// A denial with no identity records the canonical "anonymous" actor.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RecordDenialAsync_WithoutIdentity_UsesAnonymousActor()
{
@@ -103,6 +106,7 @@ public sealed class ConstraintEnforcerTests
}
/// Verifies that historized-only constraint requires historized attribute.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CheckReadTagAsync_WithHistorizedOnly_RequiresRequestedAttributeToBeHistorized()
{
@@ -122,6 +126,7 @@ public sealed class ConstraintEnforcerTests
}
/// Verifies that alarm-only constraint requires alarm attribute.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CheckReadTagAsync_WithAlarmOnly_RequiresRequestedAttributeToBeAlarm()
{
@@ -141,6 +146,7 @@ public sealed class ConstraintEnforcerTests
}
/// Verifies that attribute-only constraint fails closed for object tag.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CheckReadTagAsync_WithAttributeOnlyConstraint_FailsClosedForObjectTag()
{
@@ -257,7 +263,7 @@ public sealed class ConstraintEnforcerTests
private sealed class StubGalaxyHierarchyCache(GalaxyHierarchyCacheEntry current) : IGalaxyHierarchyCache
{
- /// Gets the current cache entry.
+ ///
public GalaxyHierarchyCacheEntry Current { get; } = current;
///
@@ -272,7 +278,10 @@ public sealed class ConstraintEnforcerTests
/// Gets the recorded canonical audit events.
public List Events { get; } = [];
- ///
+ /// Appends the audit event to the recorded list.
+ /// The audit event to record.
+ /// Token to cancel the asynchronous operation.
+ /// A task that represents the asynchronous operation.
public Task WriteAsync(AuditEvent auditEvent, CancellationToken cancellationToken = default)
{
Events.Add(auditEvent);
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Security/Authorization/GatewayGrpcAuthorizationInterceptorTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Security/Authorization/GatewayGrpcAuthorizationInterceptorTests.cs
index 0636d9a..243aa81 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Security/Authorization/GatewayGrpcAuthorizationInterceptorTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Security/Authorization/GatewayGrpcAuthorizationInterceptorTests.cs
@@ -23,6 +23,7 @@ namespace ZB.MOM.WW.MxGateway.Tests.Security.Authorization;
public sealed class GatewayGrpcAuthorizationInterceptorTests
{
/// Verifies that missing API key returns unauthenticated status.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task UnaryServerHandler_MissingApiKey_ReturnsUnauthenticated()
{
@@ -41,6 +42,7 @@ public sealed class GatewayGrpcAuthorizationInterceptorTests
}
/// Verifies that invalid API key error does not expose raw credentials.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task UnaryServerHandler_InvalidApiKey_DoesNotExposeRawCredentialInStatus()
{
@@ -59,6 +61,7 @@ public sealed class GatewayGrpcAuthorizationInterceptorTests
}
/// Verifies that valid key without required scope returns permission denied.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task UnaryServerHandler_ValidApiKeyMissingScope_ReturnsPermissionDenied()
{
@@ -77,6 +80,7 @@ public sealed class GatewayGrpcAuthorizationInterceptorTests
}
/// Verifies that valid key with scope sets request identity for the handler.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task UnaryServerHandler_ValidApiKeyWithScope_SetsRequestIdentity()
{
@@ -103,6 +107,7 @@ public sealed class GatewayGrpcAuthorizationInterceptorTests
}
/// Verifies that server stream handler requires proper scope.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ServerStreamingServerHandler_ValidApiKeyMissingScope_ReturnsPermissionDenied()
{
@@ -122,6 +127,7 @@ public sealed class GatewayGrpcAuthorizationInterceptorTests
}
/// Verifies that server stream handler allows streams with proper scope.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ServerStreamingServerHandler_ValidApiKeyWithScope_AllowsStream()
{
@@ -147,6 +153,7 @@ public sealed class GatewayGrpcAuthorizationInterceptorTests
}
/// Verifies that disabled authentication skips API key verification.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task UnaryServerHandler_AuthenticationDisabled_SkipsApiKeyVerification()
{
@@ -173,6 +180,7 @@ public sealed class GatewayGrpcAuthorizationInterceptorTests
/// that lacks the session:open scope, and asserts the interceptor denies the
/// call with before the service runs.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InterceptorComposedWithService_OpenSessionMissingScope_DeniesBeforeServiceRuns()
{
@@ -200,6 +208,7 @@ public sealed class GatewayGrpcAuthorizationInterceptorTests
/// that holds session:open, and asserts the service runs and observes the
/// interceptor-supplied identity.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InterceptorComposedWithService_OpenSessionWithScope_RunsServiceWithIdentity()
{
@@ -226,6 +235,7 @@ public sealed class GatewayGrpcAuthorizationInterceptorTests
/// because the wrapped command is a write, confirming command-scope mapping is
/// enforced through the full composition.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InterceptorComposedWithService_InvokeWriteCommandWithReadScope_DeniesBeforeServiceRuns()
{
@@ -261,6 +271,7 @@ public sealed class GatewayGrpcAuthorizationInterceptorTests
/// . Ack is a write-shaped mutation against
/// alarm state, so it carries the same scope as MxCommandKind.Write.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task UnaryServerHandler_AcknowledgeAlarmMissingScope_ReturnsPermissionDenied()
{
@@ -279,6 +290,7 @@ public sealed class GatewayGrpcAuthorizationInterceptorTests
}
/// Verifies that an API key holding invoke:write may call AcknowledgeAlarm.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task UnaryServerHandler_AcknowledgeAlarmWithScope_RunsHandler()
{
@@ -305,6 +317,7 @@ public sealed class GatewayGrpcAuthorizationInterceptorTests
/// lack . Active-alarm snapshots are part of the
/// alarm/event surface and share the same scope as StreamEvents.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ServerStreamingServerHandler_QueryActiveAlarmsMissingScope_ReturnsPermissionDenied()
{
@@ -324,6 +337,7 @@ public sealed class GatewayGrpcAuthorizationInterceptorTests
}
/// Verifies that an API key holding events:read may call QueryActiveAlarms.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ServerStreamingServerHandler_QueryActiveAlarmsWithScope_RunsHandler()
{
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Security/Tls/KestrelTlsInspectorTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Security/Tls/KestrelTlsInspectorTests.cs
index 4851090..ae43ac4 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Security/Tls/KestrelTlsInspectorTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Security/Tls/KestrelTlsInspectorTests.cs
@@ -11,16 +11,19 @@ public sealed class KestrelTlsInspectorTests
.AddInMemoryCollection(entries.ToDictionary(e => e.Key, e => (string?)e.Value))
.Build();
+ /// Verifies RequiresGeneratedCertificate returns true when an HTTPS endpoint has no certificate configured.
[Fact]
public void RequiresGeneratedCertificate_True_WhenHttpsEndpointHasNoCertificate()
=> Assert.True(KestrelTlsInspector.RequiresGeneratedCertificate(
Config(("Kestrel:Endpoints:Http:Url", "https://0.0.0.0:5120"))));
+ /// Verifies RequiresGeneratedCertificate returns false when all endpoints use plaintext.
[Fact]
public void RequiresGeneratedCertificate_False_WhenAllEndpointsPlaintext()
=> Assert.False(KestrelTlsInspector.RequiresGeneratedCertificate(
Config(("Kestrel:Endpoints:Http:Url", "http://0.0.0.0:5120"))));
+ /// Verifies RequiresGeneratedCertificate returns false when the HTTPS endpoint has its own certificate.
[Fact]
public void RequiresGeneratedCertificate_False_WhenHttpsEndpointHasOwnCertificate()
=> Assert.False(KestrelTlsInspector.RequiresGeneratedCertificate(
@@ -28,10 +31,12 @@ public sealed class KestrelTlsInspectorTests
("Kestrel:Endpoints:Http:Url", "https://0.0.0.0:5120"),
("Kestrel:Endpoints:Http:Certificate:Path", @"C:\certs\real.pfx"))));
+ /// Verifies RequiresGeneratedCertificate returns false when no endpoints are configured.
[Fact]
public void RequiresGeneratedCertificate_False_WhenNoEndpointsConfigured()
=> Assert.False(KestrelTlsInspector.RequiresGeneratedCertificate(Config()));
+ /// Verifies RequiresGeneratedCertificate returns false when the HTTPS endpoint identifies a certificate by thumbprint.
[Fact]
public void RequiresGeneratedCertificate_False_WhenHttpsEndpointHasThumbprintOnly()
=> Assert.False(KestrelTlsInspector.RequiresGeneratedCertificate(
@@ -39,6 +44,7 @@ public sealed class KestrelTlsInspectorTests
("Kestrel:Endpoints:Https:Url", "https://0.0.0.0:5120"),
("Kestrel:Endpoints:Https:Certificate:Thumbprint", "AABBCCDDEEFF00112233445566778899AABBCCDD"))));
+ /// Verifies RequiresGeneratedCertificate returns false when the HTTPS endpoint identifies a certificate by subject.
[Fact]
public void RequiresGeneratedCertificate_False_WhenHttpsEndpointHasSubjectOnly()
=> Assert.False(KestrelTlsInspector.RequiresGeneratedCertificate(
@@ -46,11 +52,13 @@ public sealed class KestrelTlsInspectorTests
("Kestrel:Endpoints:Https:Url", "https://0.0.0.0:5120"),
("Kestrel:Endpoints:Https:Certificate:Subject", "CN=myserver"))));
+ /// Verifies RequiresGeneratedCertificate returns true when the HTTPS URL is uppercase with no certificate.
[Fact]
public void RequiresGeneratedCertificate_True_WhenHttpsUrlIsUppercase()
=> Assert.True(KestrelTlsInspector.RequiresGeneratedCertificate(
Config(("Kestrel:Endpoints:Https:Url", "HTTPS://0.0.0.0:5120"))));
+ /// Verifies RequiresGeneratedCertificate returns false when a Kestrel default certificate is configured.
[Fact]
public void RequiresGeneratedCertificate_False_WhenKestrelDefaultCertificateConfigured()
=> Assert.False(KestrelTlsInspector.RequiresGeneratedCertificate(
@@ -58,6 +66,7 @@ public sealed class KestrelTlsInspectorTests
("Kestrel:Endpoints:Https:Url", "https://0.0.0.0:5120"),
("Kestrel:Certificates:Default:Path", @"C:\certs\default.pfx"))));
+ /// Verifies RequiresGeneratedCertificate returns true when mixed endpoints include one HTTPS endpoint with no certificate.
[Fact]
public void RequiresGeneratedCertificate_True_WhenMixedEndpointsAndOneHttpsHasNoCert()
=> Assert.True(KestrelTlsInspector.RequiresGeneratedCertificate(
diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Security/Tls/SelfSignedCertificateProviderTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Security/Tls/SelfSignedCertificateProviderTests.cs
index 7b8dfc8..2d40f2a 100644
--- a/src/ZB.MOM.WW.MxGateway.Tests/Security/Tls/SelfSignedCertificateProviderTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Tests/Security/Tls/SelfSignedCertificateProviderTests.cs
@@ -12,6 +12,7 @@ public sealed class SelfSignedCertificateProviderTests
private static SelfSignedCertificateProvider CreateProvider(TlsOptions options, FakeTimeProvider time)
=> new(options, NullLogger.Instance, time);
+ /// Verifies that a generated certificate has the expected SANs, EKU, and validity period.
[Fact]
public void GenerateCertificate_HasExpectedSansEkuAndValidity()
{
@@ -39,6 +40,7 @@ public sealed class SelfSignedCertificateProviderTests
o => o.Value == "1.3.6.1.5.5.7.3.1"); // serverAuth
}
+ /// Verifies that LoadOrCreate generates, persists, and reuses the same certificate thumbprint.
[Fact]
public void LoadOrCreate_GeneratesPersistsAndReuses_SameThumbprint()
{
@@ -58,6 +60,7 @@ public sealed class SelfSignedCertificateProviderTests
finally { Directory.Delete(dir, recursive: true); }
}
+ /// Verifies that LoadOrCreate regenerates the certificate when the persisted certificate has expired.
[Fact]
public void LoadOrCreate_Regenerates_WhenPersistedCertExpired()
{
@@ -77,6 +80,7 @@ public sealed class SelfSignedCertificateProviderTests
finally { Directory.Delete(dir, recursive: true); }
}
+ /// Verifies that LoadOrCreate regenerates the certificate when the persisted file is corrupt.
[Fact]
public void LoadOrCreate_Regenerates_WhenPersistedFileCorrupt()
{
@@ -92,6 +96,7 @@ public sealed class SelfSignedCertificateProviderTests
finally { Directory.Delete(dir, recursive: true); }
}
+ /// Verifies that LoadOrCreate throws when the certificate is expired and regeneration is disabled.
[Fact]
public void LoadOrCreate_Throws_WhenExpiredAndRegenerateDisabled()
{
@@ -108,6 +113,7 @@ public sealed class SelfSignedCertificateProviderTests
finally { Directory.Delete(dir, recursive: true); }
}
+ /// Verifies that LoadOrCreate throws when the self-signed certificate path is blank.
[Fact]
public void LoadOrCreate_Throws_WhenSelfSignedCertPathBlank()
{
diff --git a/src/ZB.MOM.WW.MxGateway.Worker.Tests/Bootstrap/WorkerApplicationTests.cs b/src/ZB.MOM.WW.MxGateway.Worker.Tests/Bootstrap/WorkerApplicationTests.cs
index e1155c3..5b28223 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/Bootstrap/WorkerApplicationTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/Bootstrap/WorkerApplicationTests.cs
@@ -143,10 +143,7 @@ public sealed class WorkerApplicationTests
private sealed class SucceedingPipeClient : IWorkerPipeClient
{
- /// Runs the worker pipe client successfully.
- /// Worker options.
- /// Cancellation token.
- /// Completed task.
+ ///
public Task RunAsync(
WorkerOptions options,
CancellationToken cancellationToken = default)
@@ -166,10 +163,7 @@ public sealed class WorkerApplicationTests
_exception = exception;
}
- /// Runs the worker pipe client and throws configured exception.
- /// Worker options.
- /// Cancellation token.
- /// Never completes; always throws.
+ ///
public Task RunAsync(
WorkerOptions options,
CancellationToken cancellationToken = default)
diff --git a/src/ZB.MOM.WW.MxGateway.Worker.Tests/Ipc/WorkerFrameProtocolTests.cs b/src/ZB.MOM.WW.MxGateway.Worker.Tests/Ipc/WorkerFrameProtocolTests.cs
index 4b60181..4e1ca76 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/Ipc/WorkerFrameProtocolTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/Ipc/WorkerFrameProtocolTests.cs
@@ -14,6 +14,7 @@ public sealed class WorkerFrameProtocolTests
private const string Nonce = "nonce-secret";
/// Verifies that valid envelopes round-trip through write and read.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WriteAndReadAsync_WithValidEnvelope_RoundTripsFrame()
{
@@ -32,6 +33,7 @@ public sealed class WorkerFrameProtocolTests
}
/// Verifies that wrong protocol version throws mismatch error.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadAsync_WithWrongProtocolVersion_ThrowsProtocolVersionMismatch()
{
@@ -49,6 +51,7 @@ public sealed class WorkerFrameProtocolTests
}
/// Verifies that wrong session ID throws mismatch error.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadAsync_WithWrongSessionId_ThrowsSessionMismatch()
{
@@ -72,6 +75,7 @@ public sealed class WorkerFrameProtocolTests
/// length prefix is the leading four bytes of the stream, so a four-zero-byte
/// stream is exactly a frame declaring a zero-length payload.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadAsync_WithZeroLengthPayload_ThrowsMalformedLength()
{
@@ -93,6 +97,7 @@ public sealed class WorkerFrameProtocolTests
/// A small maximum is configured so the rejection is asserted without
/// allocating a multi-megabyte buffer.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadAsync_WithPayloadAboveConfiguredMaximum_ThrowsMessageTooLarge()
{
@@ -115,6 +120,7 @@ public sealed class WorkerFrameProtocolTests
}
/// Verifies that malformed payload throws invalid envelope error.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadAsync_WithMalformedPayload_ThrowsInvalidEnvelope()
{
@@ -140,6 +146,7 @@ public sealed class WorkerFrameProtocolTests
/// payload but only supplies 50 bytes, so the inner read loop sees
/// bytesRead == 0 mid-frame.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadAsync_WhenStreamEndsMidFrame_ThrowsEndOfStream()
{
@@ -167,6 +174,7 @@ public sealed class WorkerFrameProtocolTests
/// padded out to several hundred bytes — exceeds the limit
/// without allocating anything large.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WriteAsync_WithEnvelopeAboveConfiguredMaximum_ThrowsMessageTooLarge()
{
@@ -209,6 +217,7 @@ public sealed class WorkerFrameProtocolTests
/// would weaken the writer against future serialisation
/// regressions; this test makes its rationale visible.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WriteAsync_WithEmptyEnvelope_ThrowsInvalidEnvelopeFromValidator()
{
@@ -233,6 +242,7 @@ public sealed class WorkerFrameProtocolTests
}
/// Verifies that concurrent writes produce complete serialized frames.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WriteAsync_WithConcurrentCalls_SerializesCompleteFrames()
{
@@ -262,6 +272,7 @@ public sealed class WorkerFrameProtocolTests
/// differing sizes back-to-back through one reader must parse each frame
/// using only its own payload length, never trailing pooled bytes.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadAsync_WithVaryingFrameSizes_ParsesEachFrameExactly()
{
diff --git a/src/ZB.MOM.WW.MxGateway.Worker.Tests/Ipc/WorkerPipeClientTests.cs b/src/ZB.MOM.WW.MxGateway.Worker.Tests/Ipc/WorkerPipeClientTests.cs
index 5c6dc6f..ec5c53c 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/Ipc/WorkerPipeClientTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/Ipc/WorkerPipeClientTests.cs
@@ -15,6 +15,7 @@ namespace ZB.MOM.WW.MxGateway.Worker.Tests.Ipc;
public sealed class WorkerPipeClientTests
{
/// Verifies that worker client connects and completes handshake.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_ConnectsToPipeAndCompletesHandshake()
{
@@ -83,6 +84,7 @@ public sealed class WorkerPipeClientTests
}
/// Verifies that worker client retries until pipe server becomes available.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_RetriesUntilPipeServerAppears()
{
@@ -127,6 +129,7 @@ public sealed class WorkerPipeClientTests
}
/// Verifies that worker client throws timeout if pipe never appears.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_WhenPipeNeverAppears_ThrowsTimeoutException()
{
diff --git a/src/ZB.MOM.WW.MxGateway.Worker.Tests/Ipc/WorkerPipeSessionTests.cs b/src/ZB.MOM.WW.MxGateway.Worker.Tests/Ipc/WorkerPipeSessionTests.cs
index 1300af4..2f70dbe 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/Ipc/WorkerPipeSessionTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/Ipc/WorkerPipeSessionTests.cs
@@ -20,6 +20,7 @@ public sealed class WorkerPipeSessionTests
private const string Nonce = "nonce-secret";
/// Verifies that valid gateway hello triggers worker hello and ready responses.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CompleteStartupHandshakeAsync_WithValidGatewayHello_SendsHelloThenReady()
{
@@ -51,6 +52,7 @@ public sealed class WorkerPipeSessionTests
}
/// Verifies that wrong nonce causes protocol violation fault before initialization.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CompleteStartupHandshakeAsync_WithWrongNonce_FaultsBeforeInitialization()
{
@@ -79,6 +81,7 @@ public sealed class WorkerPipeSessionTests
}
/// Verifies that unsupported protocol version causes mismatch fault before initialization.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CompleteStartupHandshakeAsync_WithWrongProtocol_FaultsBeforeInitialization()
{
@@ -106,6 +109,7 @@ public sealed class WorkerPipeSessionTests
}
/// Verifies that malformed frame causes protocol violation fault.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CompleteStartupHandshakeAsync_WithMalformedFrame_WritesWorkerFault()
{
@@ -132,6 +136,7 @@ public sealed class WorkerPipeSessionTests
}
/// Verifies that MXAccess COM creation failure produces fault instead of ready.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CompleteStartupHandshakeAsync_WhenMxAccessCreationFails_WritesFaultInsteadOfReady()
{
@@ -158,6 +163,7 @@ public sealed class WorkerPipeSessionTests
}
/// Verifies that heartbeat payload reflects current runtime snapshot.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_SendsHeartbeatPayloadFromRuntimeSnapshot()
{
@@ -211,6 +217,7 @@ public sealed class WorkerPipeSessionTests
}
/// Verifies that heartbeat reports current command correlation during execution.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_WhenCommandIsExecuting_HeartbeatReportsCurrentCorrelation()
{
@@ -258,6 +265,7 @@ public sealed class WorkerPipeSessionTests
}
/// Verifies that worker events are written to the pipe.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_WhenRuntimeHasEvents_WritesWorkerEventEnvelope()
{
@@ -297,6 +305,7 @@ public sealed class WorkerPipeSessionTests
/// current-command correlation id empty to assert the genuine-hung
/// path still fires.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_WhenStaActivityIsStale_WritesWatchdogFault()
{
@@ -343,6 +352,7 @@ public sealed class WorkerPipeSessionTests
/// in-flight correlation id so the gateway can apply its own per-command
/// timeout.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_WhenStaActivityIsStaleWithCommandInFlight_DoesNotWriteWatchdogFault()
{
@@ -403,6 +413,7 @@ public sealed class WorkerPipeSessionTests
/// heartbeat State is derived from the session state, not forced to
/// ExecutingCommand.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_AfterWatchdogFault_HeartbeatReportsFaultedState()
{
@@ -452,6 +463,7 @@ public sealed class WorkerPipeSessionTests
/// has been stale for longer than HeartbeatStuckCeiling the
/// watchdog DOES fire StaHung even with a command in flight.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_WhenStaActivityIsStaleBeyondCeilingWithCommandInFlight_WritesWatchdogFault()
{
@@ -494,6 +506,7 @@ public sealed class WorkerPipeSessionTests
/// exception if the runtime-session factory returns null, rather than
/// deferring the failure to an NRE on the next dereference.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_WhenRuntimeSessionFactoryReturnsNull_ThrowsDiagnosticException()
{
@@ -520,6 +533,7 @@ public sealed class WorkerPipeSessionTests
/// Skipping disposal on the timed-out path leaked the STA thread and
/// the MXAccess COM object.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_WhenShutdownTimesOut_StillDisposesRuntimeSession()
{
@@ -583,6 +597,7 @@ public sealed class WorkerPipeSessionTests
}
/// Verifies that shutdown drops late replies and sends shutdown ack.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_WhenShutdownArrivesDuringCommand_DropsLateReplyAndWritesShutdownAck()
{
@@ -623,6 +638,7 @@ public sealed class WorkerPipeSessionTests
}
/// Verifies that command exceptions after shutdown are dropped before ack.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_WhenCommandThrowsAfterShutdown_DropsLateFaultAndWritesShutdownAck()
{
@@ -681,6 +697,7 @@ public sealed class WorkerPipeSessionTests
/// returns true (keep reading), so a subsequent
/// WorkerShutdown still produces the normal shutdown ack.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_WhenGatewaySendsWorkerCancel_ForwardsCorrelationIdToRuntimeSession()
{
@@ -723,6 +740,7 @@ public sealed class WorkerPipeSessionTests
/// pre-handshake protocol violations); the contract this test pins
/// is the exception type/error-code and message-loop exit.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_WhenGatewaySendsUnexpectedEnvelopeBodyAfterHandshake_ThrowsAndExitsMessageLoop()
{
@@ -761,6 +779,7 @@ public sealed class WorkerPipeSessionTests
/// HeartbeatInterval. A long interval is configured so a delay-first
/// loop would fail to deliver a heartbeat inside the assertion window.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_SendsFirstHeartbeatImmediatelyOnEnteringLoop()
{
@@ -804,6 +823,7 @@ public sealed class WorkerPipeSessionTests
/// reply must be logged with a diagnostic rather than discarded
/// silently, so a stuck gateway correlation wait can be traced.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAsync_WhenReplyIsDroppedAfterShutdown_LogsDiagnostic()
{
@@ -1093,17 +1113,13 @@ public sealed class WorkerPipeSessionTests
}
}
- /// Records an informational log event.
- /// The event name.
- /// The event fields.
+ ///
public void Information(string eventName, IReadOnlyDictionary fields)
{
Record(eventName, fields);
}
- /// Records an error log event.
- /// The event name.
- /// The event fields.
+ ///
public void Error(string eventName, IReadOnlyDictionary fields)
{
Record(eventName, fields);
@@ -1194,7 +1210,7 @@ public sealed class WorkerPipeSessionTests
return new PipePair(gatewayStream, workerStream);
}
- /// Disposes pipe resources.
+ ///
public void Dispose()
{
WorkerStream.Dispose();
diff --git a/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/AlarmCommandExecutorTests.cs b/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/AlarmCommandExecutorTests.cs
index 27b2f08..15493d8 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/AlarmCommandExecutorTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/AlarmCommandExecutorTests.cs
@@ -371,28 +371,20 @@ public sealed class AlarmCommandExecutorTests
/// Gets the last alarm filter prefix.
public string? LastFilterPrefix { get; private set; }
- /// Records a subscription.
- /// The subscription expression.
- /// The session identifier.
+ ///
public void Subscribe(string subscription, string sessionId)
{
LastSubscription = subscription;
LastSessionId = sessionId;
}
- /// Records an unsubscribe request.
+ ///
public void Unsubscribe()
{
UnsubscribeCalled = true;
}
- /// Records an acknowledge request.
- /// The alarm identifier.
- /// The acknowledge comment.
- /// The operator user name.
- /// The operator node name.
- /// The operator domain.
- /// The operator full name.
+ ///
public int Acknowledge(
Guid alarmGuid, string comment, string operatorUser,
string operatorNode, string operatorDomain, string operatorFullName)
@@ -406,15 +398,7 @@ public sealed class AlarmCommandExecutorTests
return AcknowledgeReturn;
}
- /// Records an acknowledge by name request.
- /// The alarm name.
- /// The provider name.
- /// The group name.
- /// The acknowledge comment.
- /// The operator user name.
- /// The operator node name.
- /// The operator domain.
- /// The operator full name.
+ ///
public int AcknowledgeByName(
string alarmName, string providerName, string groupName,
string comment, string operatorUser, string operatorNode,
@@ -428,8 +412,7 @@ public sealed class AlarmCommandExecutorTests
/// Gets the last acknowledge by name tuple.
public (string Name, string Provider, string Group)? LastAckByNameTuple { get; private set; }
- /// Queries the active alarms with the given filter prefix.
- /// The alarm filter prefix for the query.
+ ///
public IReadOnlyList QueryActive(string? alarmFilterPrefix)
{
LastFilterPrefix = alarmFilterPrefix;
@@ -439,7 +422,7 @@ public sealed class AlarmCommandExecutorTests
/// Gets the number of poll calls.
public int PollCount { get; private set; }
- /// Increments the poll count.
+ ///
public void PollOnce()
{
PollCount++;
diff --git a/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/AlarmCommandHandlerTests.cs b/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/AlarmCommandHandlerTests.cs
index fdd004a..dd40ef9 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/AlarmCommandHandlerTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/AlarmCommandHandlerTests.cs
@@ -310,8 +310,7 @@ public sealed class AlarmCommandHandlerTests
/// Gets a value indicating whether the consumer has been disposed.
public bool Disposed { get; private set; }
- /// Subscribes to alarms with the given subscription string.
- /// The subscription reference.
+ ///
public void Subscribe(string subscription)
{
LastSubscription = subscription;
@@ -321,13 +320,7 @@ public sealed class AlarmCommandHandlerTests
}
}
- /// Acknowledges an alarm by GUID.
- /// The alarm GUID.
- /// The acknowledgment comment.
- /// The operator name.
- /// The operator node.
- /// The operator domain.
- /// The operator full name.
+ ///
public int AcknowledgeByGuid(
Guid alarmGuid, string ackComment, string ackOperatorName,
string ackOperatorNode, string ackOperatorDomain, string ackOperatorFullName)
@@ -337,15 +330,7 @@ public sealed class AlarmCommandHandlerTests
return AcknowledgeReturn;
}
- /// Acknowledges an alarm by name.
- /// The alarm name.
- /// The provider name.
- /// The alarm group name.
- /// The acknowledgment comment.
- /// The operator name.
- /// The operator node.
- /// The operator domain.
- /// The operator full name.
+ ///
public int AcknowledgeByName(
string alarmName, string providerName, string groupName,
string ackComment, string ackOperatorName, string ackOperatorNode,
@@ -359,13 +344,13 @@ public sealed class AlarmCommandHandlerTests
/// Gets the last acknowledge-by-name parameters.
public (string Name, string Provider, string Group)? LastAckByNameTuple { get; private set; }
- /// Returns a snapshot of active alarms.
+ ///
public IReadOnlyList SnapshotActiveAlarms() => SnapshotResult;
/// Gets the number of times polled.
public int PollCount { get; private set; }
- /// Polls once for alarm updates.
+ ///
public void PollOnce()
{
PollCount++;
diff --git a/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/AlarmDispatcherTests.cs b/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/AlarmDispatcherTests.cs
index 18af656..6a5dc48 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/AlarmDispatcherTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/AlarmDispatcherTests.cs
@@ -303,20 +303,13 @@ public sealed class AlarmDispatcherTests
AlarmTransitionEmitted?.Invoke(this, transition);
}
- /// Records the subscription reference.
- /// The subscription reference.
+ ///
public void Subscribe(string subscription)
{
LastSubscription = subscription;
}
- /// Records an acknowledge-by-GUID call with operator identity.
- /// The alarm GUID.
- /// The acknowledgment comment.
- /// The operator name.
- /// The operator node.
- /// The operator domain.
- /// The operator full name.
+ ///
public int AcknowledgeByGuid(
Guid alarmGuid,
string ackComment,
@@ -334,15 +327,7 @@ public sealed class AlarmDispatcherTests
return AcknowledgeReturn;
}
- /// Records an acknowledge-by-name call with alarm name, provider, and group.
- /// The alarm name.
- /// The provider name.
- /// The alarm group name.
- /// The acknowledgment comment.
- /// The operator name.
- /// The operator node.
- /// The operator domain.
- /// The operator full name.
+ ///
public int AcknowledgeByName(
string alarmName, string providerName, string groupName,
string ackComment, string ackOperatorName, string ackOperatorNode,
@@ -356,7 +341,7 @@ public sealed class AlarmDispatcherTests
/// Gets the last acknowledge-by-name tuple (alarm name, provider, group).
public (string Name, string Provider, string Group)? LastAckByNameTuple { get; private set; }
- /// Returns the current snapshot result collection.
+ ///
public IReadOnlyList SnapshotActiveAlarms()
{
return SnapshotResult;
@@ -365,7 +350,7 @@ public sealed class AlarmDispatcherTests
/// Gets the count of poll operations.
public int PollCount { get; private set; }
- /// Increments the poll count.
+ ///
public void PollOnce()
{
PollCount++;
diff --git a/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessComServerTests.cs b/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessComServerTests.cs
index e821cac..37f3501 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessComServerTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessComServerTests.cs
@@ -91,8 +91,7 @@ public sealed class MxAccessComServerTests
/// Gets the recorded method calls as strings.
public IReadOnlyList Calls => calls.ToArray();
- /// Records a Register call and returns the configured handle.
- /// The client name to record.
+ ///
public int Register(string clientName)
{
calls.Add($"Register:{clientName}");
@@ -105,103 +104,69 @@ public sealed class MxAccessComServerTests
return registerHandle;
}
- /// Records an Unregister call.
- /// The MXAccess server handle.
+ ///
public void Unregister(int serverHandle)
{
calls.Add($"Unregister:{serverHandle}");
}
- /// Records an AddItem call and returns zero.
- /// The MXAccess server handle.
- /// The item definition string to record.
+ ///
public int AddItem(int serverHandle, string itemDefinition)
{
calls.Add($"AddItem:{serverHandle}:{itemDefinition}");
return 0;
}
- /// Records an AddItem2 call and returns zero.
- /// The MXAccess server handle.
- /// The item definition string to record.
- /// The item context string to record.
+ ///
public int AddItem2(int serverHandle, string itemDefinition, string itemContext)
{
calls.Add($"AddItem2:{serverHandle}:{itemDefinition}:{itemContext}");
return 0;
}
- /// Records a RemoveItem call.
- /// The MXAccess server handle.
- /// The MXAccess item handle.
+ ///
public void RemoveItem(int serverHandle, int itemHandle)
{
calls.Add($"RemoveItem:{serverHandle}:{itemHandle}");
}
- /// Records an Advise call.
- /// The MXAccess server handle.
- /// The MXAccess item handle.
+ ///
public void Advise(int serverHandle, int itemHandle)
{
calls.Add($"Advise:{serverHandle}:{itemHandle}");
}
- /// Records an UnAdvise call.
- /// The MXAccess server handle.
- /// The MXAccess item handle.
+ ///
public void UnAdvise(int serverHandle, int itemHandle)
{
calls.Add($"UnAdvise:{serverHandle}:{itemHandle}");
}
- /// Records an AdviseSupervisory call.
- /// The MXAccess server handle.
- /// The MXAccess item handle.
+ ///
public void AdviseSupervisory(int serverHandle, int itemHandle)
{
calls.Add($"AdviseSupervisory:{serverHandle}:{itemHandle}");
}
- /// Records a Write call.
- /// The MXAccess server handle.
- /// The MXAccess item handle.
- /// The value to write.
- /// The user identifier.
+ ///
public void Write(int serverHandle, int itemHandle, object? value, int userId)
{
calls.Add($"Write:{serverHandle}:{itemHandle}:{value}:{userId}");
}
- /// Records a Write2 call.
- /// The MXAccess server handle.
- /// The MXAccess item handle.
- /// The value to write.
- /// The timestamp value.
- /// The user identifier.
+ ///
public void Write2(int serverHandle, int itemHandle, object? value, object? timestamp, int userId)
{
calls.Add($"Write2:{serverHandle}:{itemHandle}:{value}:{timestamp}:{userId}");
}
- /// Records a WriteSecured call.
- /// The MXAccess server handle.
- /// The MXAccess item handle.
- /// The current user identifier.
- /// The verifier user identifier.
- /// The value to write.
+ ///
public void WriteSecured(int serverHandle, int itemHandle, int currentUserId, int verifierUserId, object? value)
{
calls.Add($"WriteSecured:{serverHandle}:{itemHandle}:{currentUserId}:{verifierUserId}:{value}");
}
- /// Records a WriteSecured2 call.
- /// The MXAccess server handle.
- /// The MXAccess item handle.
- /// The current user identifier.
- /// The verifier user identifier.
- /// The value to write.
- /// The timestamp value.
+ ///
public void WriteSecured2(
int serverHandle, int itemHandle, int currentUserId, int verifierUserId, object? value, object? timestamp)
{
diff --git a/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessCommandExecutorTests.cs b/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessCommandExecutorTests.cs
index f9d19fa..8f93f8a 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessCommandExecutorTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessCommandExecutorTests.cs
@@ -14,6 +14,7 @@ namespace ZB.MOM.WW.MxGateway.Worker.Tests.MxAccess;
public sealed class MxAccessCommandExecutorTests
{
/// Verifies that Register command calls MXAccess on the STA thread and preserves the server handle.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_Register_CallsMxAccessOnStaAndPreservesServerHandle()
{
@@ -40,6 +41,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that Unregister command calls MXAccess on the STA thread and removes the tracked server handle.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_Unregister_CallsMxAccessOnStaAndRemovesTrackedServerHandle()
{
@@ -59,6 +61,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that Unregister preserves the HResult when MXAccess throws and does not rewrite the failure.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_UnregisterWhenMxAccessThrows_PreservesHResultAndDoesNotRewriteFailure()
{
@@ -86,6 +89,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that AddItem command calls MXAccess on the STA thread and tracks the item handle.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_AddItem_CallsMxAccessOnStaAndTracksItemHandle()
{
@@ -123,6 +127,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that AddItem2 command passes the context exactly and tracks the item handle.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_AddItem2_PassesContextExactlyAndTracksItemHandle()
{
@@ -160,6 +165,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that RemoveItem command calls MXAccess on the STA thread and removes the tracked item handle.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_RemoveItem_CallsMxAccessOnStaAndRemovesTrackedItemHandle()
{
@@ -188,6 +194,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that RemoveItem removes tracked advice after MXAccess succeeds on an advised handle.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_RemoveItemWithAdvisedHandle_RemovesTrackedAdviceAfterMxAccessSucceeds()
{
@@ -213,6 +220,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that RemoveItem preserves the HResult and keeps the tracked item handle when using a cross-server handle.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_RemoveItemWithCrossServerHandle_PreservesHResultAndKeepsTrackedItemHandle()
{
@@ -247,6 +255,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that AddItem2 preserves the HResult when MXAccess throws and does not track the item handle.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_AddItem2WhenMxAccessThrows_PreservesHResultAndDoesNotTrackItemHandle()
{
@@ -276,6 +285,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that Advise command calls MXAccess on the STA thread and tracks plain advice.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_Advise_CallsMxAccessOnStaAndTracksPlainAdvice()
{
@@ -309,6 +319,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that AdviseSupervisory calls a distinct MXAccess method and tracks supervisory advice.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_AdviseSupervisory_CallsDistinctMxAccessMethodAndTracksSupervisoryAdvice()
{
@@ -341,6 +352,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that UnAdvise command calls MXAccess on the STA thread and removes the tracked advice.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_UnAdvise_CallsMxAccessOnStaAndRemovesTrackedAdvice()
{
@@ -369,6 +381,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that Advise preserves the HResult when MXAccess throws and does not track the advice.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_AdviseWhenMxAccessThrows_PreservesHResultAndDoesNotTrackAdvice()
{
@@ -399,6 +412,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that UnAdvise preserves the HResult when MXAccess throws and keeps the tracked advice.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_UnAdviseWhenMxAccessThrows_PreservesHResultAndKeepsTrackedAdvice()
{
@@ -433,6 +447,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that SubscribeBulk runs sequential MXAccess calls and returns per-item results.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_SubscribeBulk_RunsSequentialMxAccessCallsAndReturnsPerItemResults()
{
@@ -478,6 +493,7 @@ public sealed class MxAccessCommandExecutorTests
/// one BulkWriteResult per entry in input order, including a per-entry COM
/// failure surfaced as WasSuccessful=false with the underlying HRESULT.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_WriteBulk_RunsSequentialWritesAndReturnsPerEntryResults()
{
@@ -530,6 +546,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that Write2Bulk forwards value AND timestamp to each per-entry Write2.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_Write2Bulk_ForwardsValueAndTimestampPerEntry()
{
@@ -556,6 +573,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that WriteSecuredBulk forwards both user ids per entry.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_WriteSecuredBulk_ForwardsUserIdsPerEntry()
{
@@ -580,6 +598,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that WriteSecured2Bulk forwards user ids, value, and timestamp per entry.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_WriteSecured2Bulk_ForwardsUserIdsValueAndTimestampPerEntry()
{
@@ -612,6 +631,7 @@ public sealed class MxAccessCommandExecutorTests
/// The fake COM object never fires events so the wait always times out — but
/// the lifecycle calls must still happen, in order, on the STA.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_ReadBulk_WhenTagNotCached_TakesSnapshotLifecycleAndTimesOut()
{
@@ -650,6 +670,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that ReadBulk with no payload returns an invalid request error.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_ReadBulkWithoutPayload_ReturnsInvalidRequest()
{
@@ -671,6 +692,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that UnsubscribeBulk removes items after UnAdvise failure.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_UnsubscribeBulk_RemovesItemAfterUnAdviseFailure()
{
@@ -700,6 +722,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that ShutdownGracefullyAsync cleans up handles in advice, item, server order.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ShutdownGracefullyAsync_CleansHandlesInAdviceItemServerOrder()
{
@@ -725,6 +748,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that ShutdownGracefullyAsync records cleanup failures and continues.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ShutdownGracefullyAsync_RecordsCleanupFailuresAndContinues()
{
@@ -753,6 +777,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that Register without payload returns an invalid request error.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_RegisterWithoutPayload_ReturnsInvalidRequest()
{
@@ -774,6 +799,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that AddItem without payload returns an invalid request error.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_AddItemWithoutPayload_ReturnsInvalidRequest()
{
@@ -795,6 +821,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that Advise without payload returns an invalid request error.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_AdviseWithoutPayload_ReturnsInvalidRequest()
{
@@ -816,6 +843,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that Write dispatches the converted value to MXAccess on the STA thread.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_Write_CallsMxAccessOnStaWithConvertedValue()
{
@@ -838,6 +866,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that Write2 forwards the converted value and timestamp to MXAccess.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_Write2_ForwardsValueAndTimestamp()
{
@@ -860,6 +889,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that WriteSecured forwards the operator and verifier user ids to MXAccess.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_WriteSecured_ForwardsUserIds()
{
@@ -881,6 +911,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that WriteSecured2 forwards user ids, value, and timestamp to MXAccess.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_WriteSecured2_ForwardsUserIdsValueAndTimestamp()
{
@@ -904,6 +935,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that Write without a payload returns an invalid request error.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_WriteWithoutPayload_ReturnsInvalidRequest()
{
@@ -926,6 +958,7 @@ public sealed class MxAccessCommandExecutorTests
}
/// Verifies that Write without a value returns an invalid request error.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_WriteWithoutValue_ReturnsInvalidRequest()
{
@@ -1541,9 +1574,7 @@ public sealed class MxAccessCommandExecutorTests
/// Gets the list of operations performed on this fake object.
public IReadOnlyList OperationNames => operationNames.ToArray();
- /// Registers a client and returns a server handle.
- /// Name of the client to register.
- /// The server handle for the registered client.
+ ///
public int Register(string clientName)
{
operationNames.Add($"Register:{clientName}");
@@ -1553,8 +1584,7 @@ public sealed class MxAccessCommandExecutorTests
return registerHandle;
}
- /// Unregisters a server and tracks the operation.
- /// Server handle to unregister.
+ ///
public void Unregister(int serverHandle)
{
operationNames.Add($"Unregister:{serverHandle}");
@@ -1567,10 +1597,7 @@ public sealed class MxAccessCommandExecutorTests
}
}
- /// Adds an item to the server and returns its item handle.
- /// Server handle to add the item to.
- /// Item definition string.
- /// The item handle for the added item.
+ ///
public int AddItem(
int serverHandle,
string itemDefinition)
@@ -1588,11 +1615,7 @@ public sealed class MxAccessCommandExecutorTests
return addItemHandle;
}
- /// Adds an item to the server with context and returns its item handle.
- /// Server handle to add the item to.
- /// Item definition string.
- /// Item context string.
- /// The item handle for the added item.
+ ///
public int AddItem2(
int serverHandle,
string itemDefinition,
@@ -1612,9 +1635,7 @@ public sealed class MxAccessCommandExecutorTests
return addItem2Handle;
}
- /// Removes an item from the server and tracks the operation.
- /// Server handle from which to remove the item.
- /// Item handle to remove.
+ ///
public void RemoveItem(
int serverHandle,
int itemHandle)
@@ -1630,9 +1651,7 @@ public sealed class MxAccessCommandExecutorTests
}
}
- /// Advises on item changes and tracks the operation.
- /// Server handle for the advisory subscription.
- /// Item handle to advise on.
+ ///
public void Advise(
int serverHandle,
int itemHandle)
@@ -1648,9 +1667,7 @@ public sealed class MxAccessCommandExecutorTests
}
}
- /// Removes an item advice subscription and tracks the operation.
- /// Server handle from which to remove the subscription.
- /// Item handle to remove advice from.
+ ///
public void UnAdvise(
int serverHandle,
int itemHandle)
@@ -1666,9 +1683,7 @@ public sealed class MxAccessCommandExecutorTests
}
}
- /// Advises supervisory on item changes and tracks the operation.
- /// Server handle for the supervisory subscription.
- /// Item handle to advise supervisory on.
+ ///
public void AdviseSupervisory(
int serverHandle,
int itemHandle)
@@ -1708,11 +1723,7 @@ public sealed class MxAccessCommandExecutorTests
/// Gets the thread ID on which the most recent write was called.
public int? WriteThreadId { get; private set; }
- /// Writes a value to an item and tracks the operation.
- /// Server handle for the write.
- /// Item handle to write to.
- /// Value to write.
- /// MXAccess user id for the write.
+ ///
public void Write(
int serverHandle,
int itemHandle,
@@ -1728,12 +1739,7 @@ public sealed class MxAccessCommandExecutorTests
ThrowIfWriteFailureConfigured(itemHandle);
}
- /// Writes a timestamped value to an item and tracks the operation.
- /// Server handle for the write.
- /// Item handle to write to.
- /// Value to write.
- /// Source timestamp for the write.
- /// MXAccess user id for the write.
+ ///
public void Write2(
int serverHandle,
int itemHandle,
@@ -1751,12 +1757,7 @@ public sealed class MxAccessCommandExecutorTests
ThrowIfWriteFailureConfigured(itemHandle);
}
- /// Performs a secured write to an item and tracks the operation.
- /// Server handle for the write.
- /// Item handle to write to.
- /// Operator user id.
- /// Verifier user id.
- /// Value to write.
+ ///
public void WriteSecured(
int serverHandle,
int itemHandle,
@@ -1774,13 +1775,7 @@ public sealed class MxAccessCommandExecutorTests
ThrowIfWriteFailureConfigured(itemHandle);
}
- /// Performs a secured timestamped write to an item and tracks the operation.
- /// Server handle for the write.
- /// Item handle to write to.
- /// Operator user id.
- /// Verifier user id.
- /// Value to write.
- /// Source timestamp for the write.
+ ///
public void WriteSecured2(
int serverHandle,
int itemHandle,
@@ -1825,8 +1820,7 @@ public sealed class MxAccessCommandExecutorTests
/// Gets the fake COM object.
public FakeMxAccessComObject FakeComObject { get; }
- /// Creates and returns the fake MXAccess COM object.
- /// The fake COM object.
+ ///
public object Create()
{
return FakeComObject;
diff --git a/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessLiveComCreationTests.cs b/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessLiveComCreationTests.cs
index 9479fb1..404a8fd 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessLiveComCreationTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessLiveComCreationTests.cs
@@ -15,6 +15,7 @@ public sealed class MxAccessLiveComCreationTests
private const string DefaultLiveAddItem2Context = "TestChildObject";
/// Verifies that StartAsync creates the installed MXAccess COM object on the STA thread when opted in.
+ /// A task that represents the asynchronous operation.
[LiveMxAccessFact]
public async Task StartAsync_WhenOptedIn_CreatesInstalledMxAccessComObjectOnSta()
{
@@ -24,6 +25,7 @@ public sealed class MxAccessLiveComCreationTests
}
/// Verifies that Register and Unregister round-trip server handles with installed MXAccess.
+ /// A task that represents the asynchronous operation.
[LiveMxAccessFact]
public async Task RegisterAndUnregister_WhenOptedIn_RoundTripsInstalledMxAccessServerHandle()
{
@@ -61,6 +63,7 @@ public sealed class MxAccessLiveComCreationTests
}
/// Verifies that AddItem and RemoveItem round-trip item handles with installed MXAccess.
+ /// A task that represents the asynchronous operation.
[LiveMxAccessFact]
public async Task AddItemAndRemoveItem_WhenOptedIn_RoundTripsInstalledMxAccessItemHandle()
{
@@ -129,6 +132,7 @@ public sealed class MxAccessLiveComCreationTests
}
/// Verifies that AddItem2 and RemoveItem preserve item context with installed MXAccess.
+ /// A task that represents the asynchronous operation.
[LiveMxAccessFact]
public async Task AddItem2AndRemoveItem_WhenOptedIn_PreservesContextForInstalledMxAccess()
{
@@ -198,6 +202,7 @@ public sealed class MxAccessLiveComCreationTests
}
/// Verifies that Advise and UnAdvise round-trip subscriptions with installed MXAccess.
+ /// A task that represents the asynchronous operation.
[LiveMxAccessFact]
public async Task AdviseAndUnAdvise_WhenOptedIn_RoundTripsInstalledMxAccessSubscription()
{
diff --git a/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessStaSessionTests.cs b/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessStaSessionTests.cs
index fcf563a..584437a 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessStaSessionTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessStaSessionTests.cs
@@ -18,6 +18,7 @@ public sealed class MxAccessStaSessionTests
///
/// Verifies that StartAsync creates the MXAccess COM object and attaches the event sink on the STA thread.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task StartAsync_CreatesComObjectAndAttachesEventSinkOnStaThread()
{
@@ -42,6 +43,7 @@ public sealed class MxAccessStaSessionTests
///
/// Verifies that StartAsync maps creation exceptions with HResult when the factory fails.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task StartAsync_WhenFactoryFails_MapsCreationExceptionWithHResult()
{
@@ -63,6 +65,7 @@ public sealed class MxAccessStaSessionTests
///
/// Verifies that Dispose detaches the event sink on the STA thread.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Dispose_DetachesEventSinkOnStaThread()
{
@@ -116,9 +119,7 @@ public sealed class MxAccessStaSessionTests
///
public ApartmentState? CreateApartmentState { get; private set; }
- ///
- /// Creates the COM object or throws the configured exception.
- ///
+ ///
public object Create()
{
CreateThreadId = Thread.CurrentThread.ManagedThreadId;
@@ -158,11 +159,7 @@ public sealed class MxAccessStaSessionTests
///
public string? SessionId { get; private set; }
- ///
- /// Attaches the MXAccess COM object and records thread context.
- ///
- /// MXAccess COM object to attach.
- /// Identifier of the session.
+ ///
public void Attach(
object mxAccessComObject,
string sessionId)
@@ -172,9 +169,7 @@ public sealed class MxAccessStaSessionTests
SessionId = sessionId;
}
- ///
- /// Detaches the MXAccess COM object and records thread context.
- ///
+ ///
public void Detach()
{
DetachThreadId = Thread.CurrentThread.ManagedThreadId;
@@ -188,6 +183,7 @@ public sealed class MxAccessStaSessionTests
/// This proves the fix in WorkerPipeSession (and the new internal constructor) correctly
/// wires the factory rather than leaving alarmCommandHandler null.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task StartAsync_WithAlarmCommandHandlerFactory_SubscribeAlarmsCommandReachesHandler()
{
@@ -231,6 +227,7 @@ public sealed class MxAccessStaSessionTests
/// test fails if the diagnostic regresses to a misleading message that still
/// happens to contain the word "alarm".
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task StartAsync_WithoutAlarmCommandHandlerFactory_SubscribeAlarmsReturnsInvalidRequest()
{
@@ -267,6 +264,7 @@ public sealed class MxAccessStaSessionTests
/// loop calls PollOnce on the handler via the STA within a reasonable timeout.
/// This proves polling is driven by the STA rather than the consumer's internal timer.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task StartAsync_WithAlarmCommandHandlerFactory_PollOnceCalledViaSta()
{
@@ -304,6 +302,7 @@ public sealed class MxAccessStaSessionTests
/// immediately after Dispose and stays frozen — deterministic, with no
/// elapsed-time "no further polls" window that a slow agent could race.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Dispose_StopsAlarmPollLoop()
{
@@ -352,6 +351,7 @@ public sealed class MxAccessStaSessionTests
/// alarm subscription becomes observable on the IPC fault path instead
/// of silently faulting the never-awaited poll task.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAlarmPollLoop_WhenPollOnceThrows_RecordsFaultOnEventQueue()
{
@@ -399,6 +399,7 @@ public sealed class MxAccessStaSessionTests
/// from PollOnce must reach
/// the fault-recording arm and become observable on the event queue.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RunAlarmPollLoop_WhenPollOnceThrowsInvalidOperation_RecordsFaultOnEventQueue()
{
@@ -495,52 +496,35 @@ public sealed class MxAccessStaSessionTests
get { lock (gate) return lastPollThreadId; }
}
- /// Subscribes to alarm events.
- /// The subscription descriptor.
- /// The session identifier.
+ ///
public void Subscribe(string subscription, string sessionId)
{
IsSubscribed = true;
LastSubscription = subscription;
}
- /// Unsubscribes from alarm events.
+ ///
public void Unsubscribe()
{
IsSubscribed = false;
}
- /// Acknowledges an alarm by guid.
- /// The alarm GUID.
- /// The acknowledgment comment.
- /// The operator user name.
- /// The operator node name.
- /// The operator domain.
- /// The operator full name.
+ ///
public int Acknowledge(Guid alarmGuid, string comment, string operatorUser,
string operatorNode, string operatorDomain, string operatorFullName)
=> 0;
- /// Acknowledges an alarm by name.
- /// The alarm name.
- /// The provider name.
- /// The alarm group name.
- /// The acknowledgment comment.
- /// The operator user name.
- /// The operator node name.
- /// The operator domain.
- /// The operator full name.
+ ///
public int AcknowledgeByName(string alarmName, string providerName, string groupName,
string comment, string operatorUser, string operatorNode,
string operatorDomain, string operatorFullName)
=> 0;
- /// Queries active alarms.
- /// Optional alarm name filter prefix.
+ ///
public IReadOnlyList QueryActive(string? alarmFilterPrefix)
=> Array.Empty();
- /// Polls for alarm events once.
+ ///
public void PollOnce()
{
lock (gate)
diff --git a/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessValueCacheTests.cs b/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessValueCacheTests.cs
index 14b2a8e..7e5cb4f 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessValueCacheTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/MxAccess/MxAccessValueCacheTests.cs
@@ -115,6 +115,7 @@ public sealed class MxAccessValueCacheTests
}
/// Verifies that TryWaitForUpdate returns true when the cache is updated after the baseline.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task TryWaitForUpdate_ReturnsTrue_WhenSetFiresAfterBaselineVersion()
{
diff --git a/src/ZB.MOM.WW.MxGateway.Worker.Tests/Sta/StaCommandDispatcherTests.cs b/src/ZB.MOM.WW.MxGateway.Worker.Tests/Sta/StaCommandDispatcherTests.cs
index 7987190..ee189c6 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/Sta/StaCommandDispatcherTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/Sta/StaCommandDispatcherTests.cs
@@ -18,6 +18,7 @@ public sealed class StaCommandDispatcherTests
///
/// Verifies commands execute on the STA thread in queue order.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_ExecutesCommandsOnStaInQueueOrder()
{
@@ -41,6 +42,7 @@ public sealed class StaCommandDispatcherTests
///
/// Verifies executor exceptions are captured as HResult in the reply without exposing message details.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_WhenExecutorThrows_ReturnsFailureReplyWithHResult()
{
@@ -64,6 +66,7 @@ public sealed class StaCommandDispatcherTests
///
/// Verifies cancellation before execution prevents the command from running.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_WhenCanceledBeforeExecution_ReturnsCanceledReplyWithoutExecuting()
{
@@ -96,6 +99,7 @@ public sealed class StaCommandDispatcherTests
/// observed and ignored" from "cancel never checked"; it only proves the
/// in-flight command is not aborted.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_WhenCanceledWhileExecuting_DoesNotAbortInFlightCommand()
{
@@ -121,6 +125,7 @@ public sealed class StaCommandDispatcherTests
///
/// Verifies shutdown rejects new dispatch attempts.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DispatchAsync_WhenShutdownRequested_RejectsNewCommands()
{
@@ -138,6 +143,7 @@ public sealed class StaCommandDispatcherTests
///
/// Verifies shutdown allows the current command to complete but rejects queued commands.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RequestShutdown_RejectsQueuedCommandButLetsCurrentCommandFinish()
{
@@ -162,6 +168,7 @@ public sealed class StaCommandDispatcherTests
///
/// Verifies heartbeat reports current command correlation ID and pending command count.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task PopulateHeartbeat_ReportsCurrentCorrelationAndPendingCount()
{
diff --git a/src/ZB.MOM.WW.MxGateway.Worker.Tests/Sta/StaMessagePumpTests.cs b/src/ZB.MOM.WW.MxGateway.Worker.Tests/Sta/StaMessagePumpTests.cs
index b9eeba8..3f4e30a 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/Sta/StaMessagePumpTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/Sta/StaMessagePumpTests.cs
@@ -37,6 +37,7 @@ public sealed class StaMessagePumpTests
///
/// Verifies that WaitForWorkOrMessages returns promptly when the wake event is already signalled.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WaitForWorkOrMessages_WakeEventAlreadySignalled_ReturnsImmediately()
{
@@ -60,6 +61,7 @@ public sealed class StaMessagePumpTests
///
/// Verifies that WaitForWorkOrMessages wakes when the wake event is signalled from another thread.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WaitForWorkOrMessages_WakeEventSignalledDuringWait_Returns()
{
@@ -89,6 +91,7 @@ public sealed class StaMessagePumpTests
///
/// Verifies that WaitForWorkOrMessages returns on timeout when the wake event is never signalled.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WaitForWorkOrMessages_WakeEventNeverSignalled_ReturnsAfterTimeout()
{
@@ -113,6 +116,7 @@ public sealed class StaMessagePumpTests
///
/// Verifies that a zero timeout (the TimeSpan.Zero conversion branch) returns without blocking.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WaitForWorkOrMessages_ZeroTimeout_ReturnsWithoutBlocking()
{
@@ -137,6 +141,7 @@ public sealed class StaMessagePumpTests
///
/// Verifies that PumpPendingMessages returns zero when the STA thread message queue is empty.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task PumpPendingMessages_NoMessagesPosted_ReturnsZero()
{
@@ -155,6 +160,7 @@ public sealed class StaMessagePumpTests
///
/// Verifies that PumpPendingMessages dispatches and counts messages posted to the STA thread.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task PumpPendingMessages_MessagesPostedToStaThread_ReturnsCountProcessed()
{
@@ -179,6 +185,7 @@ public sealed class StaMessagePumpTests
///
/// Verifies that WaitForWorkOrMessages returns once a Windows message is posted to the STA thread.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WaitForWorkOrMessages_WindowsMessagePosted_ReturnsForInputAvailable()
{
diff --git a/src/ZB.MOM.WW.MxGateway.Worker.Tests/Sta/StaRuntimeTests.cs b/src/ZB.MOM.WW.MxGateway.Worker.Tests/Sta/StaRuntimeTests.cs
index ebccf33..17ccb2b 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/Sta/StaRuntimeTests.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/Sta/StaRuntimeTests.cs
@@ -8,6 +8,7 @@ namespace ZB.MOM.WW.MxGateway.Worker.Tests.Sta;
public sealed class StaRuntimeTests
{
/// Verifies that InvokeAsync executes commands on the STA thread.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InvokeAsync_ExecutesCommandOnStaThread()
{
@@ -35,6 +36,7 @@ public sealed class StaRuntimeTests
/// correct dispatch past an arbitrary millisecond budget, which would be a
/// false failure.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InvokeAsync_WakesIdlePumpForQueuedCommand()
{
@@ -84,6 +86,7 @@ public sealed class StaRuntimeTests
}
/// Verifies that InvokeAsync faults the returned task when a command raises an exception without stopping the runtime.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InvokeAsync_CommandException_FaultsReturnedTaskWithoutStoppingRuntime()
{
@@ -109,6 +112,7 @@ public sealed class StaRuntimeTests
/// assertion. The test pins the exact type so a regression that
/// reverts to a plain InvalidOperationException fails here.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InvokeAsync_AfterShutdown_ReturnsFaultedTask()
{
@@ -164,14 +168,14 @@ public sealed class StaRuntimeTests
/// The thread ID where Uninitialize was called.
public int? UninitializeThreadId { get; private set; }
- /// Initializes the COM apartment and records the calling thread.
+ ///
public void Initialize()
{
InitializeCount++;
InitializeThreadId = Thread.CurrentThread.ManagedThreadId;
}
- /// Uninitializes the COM apartment and records the calling thread.
+ ///
public void Uninitialize()
{
UninitializeCount++;
diff --git a/src/ZB.MOM.WW.MxGateway.Worker.Tests/TestSupport/FakeRuntimeSession.cs b/src/ZB.MOM.WW.MxGateway.Worker.Tests/TestSupport/FakeRuntimeSession.cs
index e361819..0632629 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/TestSupport/FakeRuntimeSession.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/TestSupport/FakeRuntimeSession.cs
@@ -46,11 +46,7 @@ internal sealed class FakeRuntimeSession : IWorkerRuntimeSession
/// Gets a value indicating whether Dispose was called.
public bool Disposed { get; private set; }
- /// Starts the worker session with the given session ID and process ID.
- /// The session identifier.
- /// The worker process ID.
- /// Cancellation token.
- /// Worker ready response.
+ ///
public Task StartAsync(
string sessionId,
int workerProcessId,
@@ -65,9 +61,7 @@ internal sealed class FakeRuntimeSession : IWorkerRuntimeSession
});
}
- /// Dispatches a command to the STA thread.
- /// The command to dispatch.
- /// The command reply.
+ ///
public Task DispatchAsync(StaCommand command)
{
return Task.Run(
@@ -112,8 +106,7 @@ internal sealed class FakeRuntimeSession : IWorkerRuntimeSession
});
}
- /// Captures current heartbeat snapshot.
- /// Current runtime heartbeat snapshot.
+ ///
public WorkerRuntimeHeartbeatSnapshot CaptureHeartbeat()
{
lock (gate)
@@ -122,9 +115,7 @@ internal sealed class FakeRuntimeSession : IWorkerRuntimeSession
}
}
- /// Drains queued events up to the specified limit.
- /// Maximum events to drain; 0 drains all.
- /// The drained events.
+ ///
public IReadOnlyList DrainEvents(uint maxEvents)
{
lock (gate)
@@ -142,8 +133,7 @@ internal sealed class FakeRuntimeSession : IWorkerRuntimeSession
}
}
- /// Drains a pending fault if any.
- /// Pending fault or null.
+ ///
public WorkerFault? DrainFault()
{
return null;
@@ -195,9 +185,7 @@ internal sealed class FakeRuntimeSession : IWorkerRuntimeSession
}
}
- /// Cancels command by correlation ID.
- /// The command correlation ID.
- /// True if cancelled; false otherwise.
+ ///
public bool CancelCommand(string correlationId)
{
lock (gate)
@@ -207,16 +195,13 @@ internal sealed class FakeRuntimeSession : IWorkerRuntimeSession
}
}
- /// Requests graceful shutdown.
+ ///
public void RequestShutdown()
{
releaseDispatch.Set();
}
- /// Shuts down gracefully within the specified timeout.
- /// Shutdown timeout period.
- /// Cancellation token.
- /// Shutdown result.
+ ///
public Task ShutdownGracefullyAsync(
TimeSpan timeout,
CancellationToken cancellationToken = default)
@@ -257,7 +242,7 @@ internal sealed class FakeRuntimeSession : IWorkerRuntimeSession
}
}
- /// Disposes resources.
+ ///
public void Dispose()
{
Disposed = true;
diff --git a/src/ZB.MOM.WW.MxGateway.Worker.Tests/TestSupport/NoopMxAccessServer.cs b/src/ZB.MOM.WW.MxGateway.Worker.Tests/TestSupport/NoopMxAccessServer.cs
index 1754ed2..9682fac 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/TestSupport/NoopMxAccessServer.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/TestSupport/NoopMxAccessServer.cs
@@ -46,20 +46,30 @@ internal sealed class NoopMxAccessServer : IMxAccessServer
{
}
- ///
+ /// Adds a buffered item and returns an item handle; no-op for testing.
+ /// Server handle the item belongs to.
+ /// Item reference definition.
+ /// Caller-supplied item context.
+ /// Always 0 for testing.
public int AddBufferedItem(int serverHandle, string itemDefinition, string itemContext) => 0;
- ///
+ /// Sets the buffered update interval; no-op for testing.
+ /// Server handle the interval applies to.
+ /// Update interval in milliseconds.
public void SetBufferedUpdateInterval(int serverHandle, int updateIntervalMilliseconds)
{
}
- ///
+ /// Suspends updates for an item; no-op for testing.
+ /// Server handle the item belongs to.
+ /// Item handle to suspend.
public void Suspend(int serverHandle, int itemHandle)
{
}
- ///
+ /// Activates updates for an item; no-op for testing.
+ /// Server handle the item belongs to.
+ /// Item handle to activate.
public void Activate(int serverHandle, int itemHandle)
{
}
@@ -84,9 +94,14 @@ internal sealed class NoopMxAccessServer : IMxAccessServer
{
}
- ///
+ /// Authenticates a user by name and password; always returns 0 for testing.
+ /// User name to authenticate.
+ /// User password.
+ /// Always 0 for testing.
public int AuthenticateUser(string userName, string password) => 0;
- ///
+ /// Resolves an ArchestrA user name to an identifier; always returns 0 for testing.
+ /// User name to resolve.
+ /// Always 0 for testing.
public int ArchestrAUserToId(string userName) => 0;
}
diff --git a/src/ZB.MOM.WW.MxGateway.Worker.Tests/TestSupport/WorkerFrameTestHelpers.cs b/src/ZB.MOM.WW.MxGateway.Worker.Tests/TestSupport/WorkerFrameTestHelpers.cs
index 4a78baf..d9d633b 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker.Tests/TestSupport/WorkerFrameTestHelpers.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker.Tests/TestSupport/WorkerFrameTestHelpers.cs
@@ -12,6 +12,7 @@ internal static class WorkerFrameTestHelpers
{
/// Builds a length-prefixed frame from a protobuf message.
/// Message to serialize into the frame payload.
+ /// A byte array containing the length-prefixed frame.
public static byte[] CreateFrame(IMessage message)
{
return CreateFrame(message.ToByteArray());
@@ -19,6 +20,7 @@ internal static class WorkerFrameTestHelpers
/// Builds a length-prefixed frame from a raw payload.
/// Payload bytes to wrap in a frame.
+ /// A byte array containing the length-prefixed frame.
public static byte[] CreateFrame(byte[] payload)
{
byte[] frame = new byte[sizeof(uint) + payload.Length];
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/Bootstrap/WorkerConsoleLogger.cs b/src/ZB.MOM.WW.MxGateway.Worker/Bootstrap/WorkerConsoleLogger.cs
index 68c98d4..534d72d 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/Bootstrap/WorkerConsoleLogger.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/Bootstrap/WorkerConsoleLogger.cs
@@ -16,17 +16,13 @@ public sealed class WorkerConsoleLogger : IWorkerLogger
_writer = writer ?? throw new ArgumentNullException(nameof(writer));
}
- /// Writes an informational log entry.
- /// Name of the event being logged.
- /// Event fields and values to log.
+ ///
public void Information(string eventName, IReadOnlyDictionary fields)
{
Write("Information", eventName, fields);
}
- /// Writes an error log entry.
- /// Name of the event being logged.
- /// Event fields and values to log.
+ ///
public void Error(string eventName, IReadOnlyDictionary fields)
{
Write("Error", eventName, fields);
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/Bootstrap/WorkerLogRedactor.cs b/src/ZB.MOM.WW.MxGateway.Worker/Bootstrap/WorkerLogRedactor.cs
index 25152aa..948cfaf 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/Bootstrap/WorkerLogRedactor.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/Bootstrap/WorkerLogRedactor.cs
@@ -28,6 +28,7 @@ public static class WorkerLogRedactor
/// Redacts sensitive field values from a log field dictionary.
///
/// Dictionary of field names and values.
+ /// A new dictionary with sensitive values replaced by the redaction marker.
public static Dictionary RedactFields(IReadOnlyDictionary fields)
{
Dictionary redactedFields = [];
@@ -45,6 +46,7 @@ public static class WorkerLogRedactor
///
/// Name of the field to check.
/// Value to redact if sensitive.
+ /// The original value if not sensitive; otherwise .
public static object? RedactValue(string fieldName, object? value)
{
if (value is null)
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/Conversion/MxStatusProxyConverter.cs b/src/ZB.MOM.WW.MxGateway.Worker/Conversion/MxStatusProxyConverter.cs
index aad07a4..00a97ca 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/Conversion/MxStatusProxyConverter.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/Conversion/MxStatusProxyConverter.cs
@@ -11,6 +11,7 @@ public sealed class MxStatusProxyConverter
{
/// Converts a single status object to a protobuf message, reflecting all fields and diagnostics.
/// COM status object to convert.
+ /// The converted protobuf status message.
public MxStatusProxy Convert(object status)
{
if (status is null)
@@ -38,6 +39,7 @@ public sealed class MxStatusProxyConverter
/// Converts an array of status objects, handling nulls gracefully.
/// Array of COM status objects; null returns empty list.
+ /// A read-only list of converted status messages.
public IReadOnlyList ConvertMany(Array? statuses)
{
if (statuses is null)
@@ -67,6 +69,7 @@ public sealed class MxStatusProxyConverter
/// Preserves completion-only status bytes as a diagnostic hex string since they cannot be unpacked.
/// Status bytes to encode as hex string.
+ /// A hex-encoded diagnostic string.
public string PreserveCompletionOnlyStatusBytes(byte[] statusBytes)
{
if (statusBytes is null)
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/Ipc/IWorkerPipeClient.cs b/src/ZB.MOM.WW.MxGateway.Worker/Ipc/IWorkerPipeClient.cs
index 37bad96..c42b21d 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/Ipc/IWorkerPipeClient.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/Ipc/IWorkerPipeClient.cs
@@ -10,6 +10,7 @@ public interface IWorkerPipeClient
/// Connects to the gateway and runs the worker until the session ends or is cancelled.
/// Configuration options.
/// Token to cancel the asynchronous operation.
+ /// A task that represents the asynchronous operation.
Task RunAsync(
WorkerOptions options,
CancellationToken cancellationToken = default);
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerFrameReader.cs b/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerFrameReader.cs
index 3ff27a0..781c6a8 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerFrameReader.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerFrameReader.cs
@@ -27,6 +27,7 @@ public sealed class WorkerFrameReader
/// Reads and validates a single length-prefixed frame from the stream.
/// Token to cancel the asynchronous operation.
+ /// A task that resolves to the parsed .
public async Task ReadAsync(CancellationToken cancellationToken = default)
{
byte[] lengthPrefix = new byte[sizeof(uint)];
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerFrameWriter.cs b/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerFrameWriter.cs
index 478f6eb..a80d548 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerFrameWriter.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerFrameWriter.cs
@@ -28,6 +28,7 @@ public sealed class WorkerFrameWriter
/// Writes a worker envelope frame to the stream with length prefix.
/// Worker envelope to write.
/// Token to cancel the asynchronous operation.
+ /// A task that represents the asynchronous operation.
public async Task WriteAsync(
WorkerEnvelope envelope,
CancellationToken cancellationToken = default)
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerPipeClient.cs b/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerPipeClient.cs
index bfba1be..ab47518 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerPipeClient.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerPipeClient.cs
@@ -139,11 +139,7 @@ public sealed class WorkerPipeClient : IWorkerPipeClient
_connectAttemptTimeoutMilliseconds = connectAttemptTimeoutMilliseconds;
}
- ///
- /// Runs the worker by connecting to the gateway and executing the frame protocol.
- ///
- /// Worker configuration options.
- /// Token to cancel the asynchronous operation.
+ ///
public async Task RunAsync(
WorkerOptions options,
CancellationToken cancellationToken = default)
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerPipeSession.cs b/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerPipeSession.cs
index fa9f297..903eff8 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerPipeSession.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/Ipc/WorkerPipeSession.cs
@@ -106,6 +106,7 @@ public sealed class WorkerPipeSession
/// Runs the worker session, completing the handshake and processing messages until cancellation.
/// Token to cancel the asynchronous operation.
+ /// A task that represents the asynchronous operation.
public async Task RunAsync(CancellationToken cancellationToken = default)
{
// Worker-025: the factory delegate itself is null-checked in the
@@ -142,6 +143,7 @@ public sealed class WorkerPipeSession
/// Completes the gateway startup handshake using default MXAccess initialization.
/// Token to cancel the asynchronous operation.
+ /// A task that represents the asynchronous operation.
public Task CompleteStartupHandshakeAsync(CancellationToken cancellationToken = default)
{
return CompleteStartupHandshakeAsync(InitializeMxAccessAsync, cancellationToken);
@@ -150,6 +152,7 @@ public sealed class WorkerPipeSession
/// Completes the gateway startup handshake with custom MXAccess initialization that returns void.
/// Async function to initialize MXAccess.
/// Token to cancel the asynchronous operation.
+ /// A task that represents the asynchronous operation.
public async Task CompleteStartupHandshakeAsync(
Func initializeMxAccessAsync,
CancellationToken cancellationToken = default)
@@ -171,6 +174,7 @@ public sealed class WorkerPipeSession
/// Completes the gateway startup handshake with custom MXAccess initialization that returns WorkerReady.
/// Async function to initialize MXAccess and return ready state.
/// Token to cancel the asynchronous operation.
+ /// A task that represents the asynchronous operation.
public async Task CompleteStartupHandshakeAsync(
Func> initializeMxAccessAsync,
CancellationToken cancellationToken = default)
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/AlarmDispatcher.cs b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/AlarmDispatcher.cs
index 7a9bce9..9df083f 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/AlarmDispatcher.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/AlarmDispatcher.cs
@@ -154,6 +154,7 @@ public sealed class AlarmDispatcher : IDisposable
/// protos for the
/// QueryActiveAlarms RPC's ConditionRefresh stream.
///
+ /// The currently-active alarms as protos.
public IReadOnlyList SnapshotActiveAlarms()
{
if (disposed) throw new ObjectDisposedException(nameof(AlarmDispatcher));
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/AlarmRecordTransitionMapper.cs b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/AlarmRecordTransitionMapper.cs
index fefa0c9..ff6b138 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/AlarmRecordTransitionMapper.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/AlarmRecordTransitionMapper.cs
@@ -24,6 +24,7 @@ public static class AlarmRecordTransitionMapper
/// .
///
/// The state XML string from AVEVA (e.g., UNACK_ALM, ACK_RTN).
+ /// The corresponding , or for unknown values.
public static MxAlarmStateKind ParseStateKind(string? stateXml)
{
if (string.IsNullOrWhiteSpace(stateXml)) return MxAlarmStateKind.Unspecified;
@@ -51,6 +52,7 @@ public static class AlarmRecordTransitionMapper
///
/// The previous alarm state kind.
/// The current alarm state kind.
+ /// The proto representing the state change, or when no mapped kind applies.
public static AlarmTransitionKind MapTransition(
MxAlarmStateKind previous,
MxAlarmStateKind current)
@@ -87,6 +89,7 @@ public static class AlarmRecordTransitionMapper
/// The provider name, or null.
/// The group name, or null.
/// The alarm name, or null.
+ /// The composed full reference string in Provider!Group.AlarmName format.
public static string ComposeFullReference(string? providerName, string? groupName, string? alarmName)
{
string provider = providerName ?? string.Empty;
@@ -113,6 +116,7 @@ public static class AlarmRecordTransitionMapper
/// e.g. "13:26:14.709".
/// Offset of the producer's local time vs UTC, in minutes.
/// DST adjustment already applied to local time, in minutes.
+ /// The UTC , or when the date or time cannot be parsed.
public static DateTime ParseTransitionTimestampUtc(
string? xmlDate,
string? xmlTime,
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/IAlarmCommandHandler.cs b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/IAlarmCommandHandler.cs
index bad5680..6cc458e 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/IAlarmCommandHandler.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/IAlarmCommandHandler.cs
@@ -28,6 +28,7 @@ public interface IAlarmCommandHandler : IDisposable
/// The operator node name.
/// The operator domain name.
/// The operator full name.
+ /// AVEVA's native status code (0 = success).
int Acknowledge(
Guid alarmGuid,
string comment,
@@ -48,6 +49,7 @@ public interface IAlarmCommandHandler : IDisposable
/// The operator node name.
/// The operator domain name.
/// The operator full name.
+ /// AVEVA's native status code (0 = success).
int AcknowledgeByName(
string alarmName,
string providerName,
@@ -63,6 +65,7 @@ public interface IAlarmCommandHandler : IDisposable
/// prefix matched against AlarmFullReference.
///
/// Optional prefix to filter alarms by.
+ /// The currently active alarms matching the filter, or all alarms when no filter is given.
IReadOnlyList QueryActive(string? alarmFilterPrefix);
///
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/IMxAccessAlarmConsumer.cs b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/IMxAccessAlarmConsumer.cs
index b3a18cf..4bfc1b0 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/IMxAccessAlarmConsumer.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/IMxAccessAlarmConsumer.cs
@@ -101,6 +101,7 @@ public interface IMxAccessAlarmConsumer : IDisposable
/// ConditionRefresh path — operator clients call this after reconnect
/// to seed local Part 9 state.
///
+ /// The most recently parsed snapshot of active alarm records.
IReadOnlyList SnapshotActiveAlarms();
///
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/IWorkerRuntimeSession.cs b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/IWorkerRuntimeSession.cs
index 0785e0b..da4317a 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/IWorkerRuntimeSession.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/IWorkerRuntimeSession.cs
@@ -34,6 +34,7 @@ public interface IWorkerRuntimeSession : IDisposable
///
/// Captures a heartbeat snapshot of the runtime state.
///
+ /// A snapshot of the current worker runtime heartbeat state.
WorkerRuntimeHeartbeatSnapshot CaptureHeartbeat();
///
@@ -46,6 +47,7 @@ public interface IWorkerRuntimeSession : IDisposable
///
/// Drains a pending fault from the queue, if any.
///
+ /// The pending fault, or null if no fault is queued.
WorkerFault? DrainFault();
///
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessCommandExecutor.cs b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessCommandExecutor.cs
index 446be67..a94af69 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessCommandExecutor.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessCommandExecutor.cs
@@ -82,11 +82,7 @@ public sealed class MxAccessCommandExecutor : IStaCommandExecutor
this.pumpStep = pumpStep ?? (static () => { });
}
- ///
- /// Executes an MXAccess command and returns the reply.
- ///
- /// STA command to execute.
- /// Command reply with result or error details.
+ ///
public MxCommandReply Execute(StaCommand command)
{
if (command is null)
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessEventMapper.cs b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessEventMapper.cs
index 3f3f40b..592bdec 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessEventMapper.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessEventMapper.cs
@@ -37,6 +37,7 @@ public sealed class MxAccessEventMapper
/// Item quality code from MXAccess.
/// Item timestamp from MXAccess.
/// Array of MxStatusProxy values from MXAccess.
+ /// The constructed for this data-change notification.
public MxEvent CreateOnDataChange(
string sessionId,
int serverHandle,
@@ -65,6 +66,7 @@ public sealed class MxAccessEventMapper
/// Handle returned by the worker.
/// Handle returned by the worker.
/// Array of MxStatusProxy values from MXAccess.
+ /// The constructed for this write-complete notification.
public MxEvent CreateOnWriteComplete(
string sessionId,
int serverHandle,
@@ -87,6 +89,7 @@ public sealed class MxAccessEventMapper
/// Handle returned by the worker.
/// Handle returned by the worker.
/// Array of MxStatusProxy values from MXAccess.
+ /// The constructed for this operation-complete notification.
public MxEvent CreateOperationComplete(
string sessionId,
int serverHandle,
@@ -124,6 +127,7 @@ public sealed class MxAccessEventMapper
/// Alarm taxonomy bucket from the Galaxy template.
/// Human-readable alarm description.
/// Array of MxStatusProxy values from MXAccess.
+ /// The constructed for this alarm-transition notification.
public MxEvent CreateOnAlarmTransition(
string sessionId,
string alarmFullReference,
@@ -178,6 +182,7 @@ public sealed class MxAccessEventMapper
/// Array of quality values from MXAccess.
/// Array of timestamp values from MXAccess.
/// Array of MxStatusProxy values from MXAccess.
+ /// The constructed for this buffered data-change notification.
public MxEvent CreateOnBufferedDataChange(
string sessionId,
int serverHandle,
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessEventQueue.cs b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessEventQueue.cs
index ae8393b..a126bfe 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessEventQueue.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessEventQueue.cs
@@ -148,6 +148,7 @@ public sealed class MxAccessEventQueue
/// Attempts to dequeue the next event without removing it if empty.
///
/// The dequeued event if successful; null if queue is empty.
+ /// true if an event was dequeued; false if the queue was empty.
public bool TryDequeue(out WorkerEvent? workerEvent)
{
lock (syncRoot)
@@ -167,6 +168,7 @@ public sealed class MxAccessEventQueue
/// Drains up to maxEvents from the queue; if maxEvents is 0, drains all events.
///
/// Maximum number of events to drain; 0 means drain all.
+ /// The drained events in FIFO order.
public IReadOnlyList Drain(uint maxEvents)
{
lock (syncRoot)
@@ -209,6 +211,7 @@ public sealed class MxAccessEventQueue
///
/// Returns and clears the fault so it is not reported twice.
///
+ /// The pending fault, or null if no fault has been recorded or it was already drained.
public WorkerFault? DrainFault()
{
lock (syncRoot)
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessHandleRegistry.cs b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessHandleRegistry.cs
index 1e8526f..f0d4588 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessHandleRegistry.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessHandleRegistry.cs
@@ -66,6 +66,7 @@ public sealed class MxAccessHandleRegistry
/// Checks if the registry contains the specified server handle.
/// Handle returned by the worker.
+ /// true if the server handle is registered; otherwise false.
public bool ContainsServerHandle(int serverHandle)
{
return serverHandles.ContainsKey(serverHandle);
@@ -106,6 +107,7 @@ public sealed class MxAccessHandleRegistry
/// Checks if the registry contains the specified item handle.
/// Handle returned by the worker.
/// Handle returned by the worker.
+ /// true if the item handle is registered; otherwise false.
public bool ContainsItemHandle(
int serverHandle,
int itemHandle)
@@ -149,6 +151,7 @@ public sealed class MxAccessHandleRegistry
/// Handle returned by the worker.
/// Handle returned by the worker.
/// Type of advice to check.
+ /// true if the advice handle is registered; otherwise false.
public bool ContainsAdviceHandle(
int serverHandle,
int itemHandle,
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessSession.cs b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessSession.cs
index c89c667..99d0a52 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessSession.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessSession.cs
@@ -47,6 +47,7 @@ public sealed class MxAccessSession : IDisposable
/// Creates a WorkerReady message with session metadata.
/// Process ID of the worker.
+ /// A populated protobuf message.
public WorkerReady CreateWorkerReady(int workerProcessId)
{
return new WorkerReady
@@ -77,6 +78,7 @@ public sealed class MxAccessSession : IDisposable
/// Optional handle registry; a fresh one is created when null.
/// Optional value cache; a fresh one is created when null.
/// Optional creation thread id; defaults to the current managed thread id.
+ /// A new wired to the supplied test doubles.
///
/// Thrown when is the production
/// . Tests must pass a test
@@ -110,6 +112,7 @@ public sealed class MxAccessSession : IDisposable
/// Factory to create the MXAccess COM object.
/// Event sink to attach to the COM object.
/// Identifier of the session.
+ /// A fully initialized ready for use.
public static MxAccessSession Create(
IMxAccessComObjectFactory factory,
IMxAccessEventSink eventSink,
@@ -176,6 +179,7 @@ public sealed class MxAccessSession : IDisposable
/// Registers a client with MXAccess and returns the server handle.
/// Name of the client to register.
+ /// The MXAccess server handle for the registered client.
public int Register(string clientName)
{
ThrowIfDisposed();
@@ -199,6 +203,7 @@ public sealed class MxAccessSession : IDisposable
/// Adds an item to an MXAccess server and returns the item handle.
/// Handle returned by the worker.
/// Definition or address of the item to add.
+ /// The MXAccess item handle for the added item.
public int AddItem(
int serverHandle,
string itemDefinition)
@@ -220,6 +225,7 @@ public sealed class MxAccessSession : IDisposable
/// Handle returned by the worker.
/// Definition or address of the item to add.
/// Context string for the item.
+ /// The MXAccess item handle for the added item.
public int AddItem2(
int serverHandle,
string itemDefinition,
@@ -375,6 +381,7 @@ public sealed class MxAccessSession : IDisposable
/// Adds multiple items in bulk, returning success/failure results.
/// Handle returned by the worker.
/// Enumerable of item definitions to add.
+ /// Per-item success or failure results in the same order as .
public IReadOnlyList AddItemBulk(
int serverHandle,
IEnumerable tagAddresses)
@@ -411,6 +418,7 @@ public sealed class MxAccessSession : IDisposable
/// Advises on multiple items in bulk, returning success/failure results.
/// Handle returned by the worker.
/// Enumerable of item handles to advise on.
+ /// Per-item success or failure results in the same order as .
public IReadOnlyList AdviseItemBulk(
int serverHandle,
IEnumerable itemHandles)
@@ -441,6 +449,7 @@ public sealed class MxAccessSession : IDisposable
/// Removes multiple items in bulk, returning success/failure results.
/// Handle returned by the worker.
/// Enumerable of item handles to remove.
+ /// Per-item success or failure results in the same order as .
public IReadOnlyList RemoveItemBulk(
int serverHandle,
IEnumerable itemHandles)
@@ -471,6 +480,7 @@ public sealed class MxAccessSession : IDisposable
/// Removes advice subscriptions from multiple items in bulk, returning success/failure results.
/// Handle returned by the worker.
/// Enumerable of item handles to unadvise.
+ /// Per-item success or failure results in the same order as .
public IReadOnlyList UnAdviseItemBulk(
int serverHandle,
IEnumerable itemHandles)
@@ -501,6 +511,7 @@ public sealed class MxAccessSession : IDisposable
/// Adds multiple items and subscribes to them in bulk, returning success/failure results.
/// Handle returned by the worker.
/// Enumerable of item definitions to add and subscribe to.
+ /// Per-item success or failure results in the same order as .
public IReadOnlyList SubscribeBulk(
int serverHandle,
IEnumerable tagAddresses)
@@ -545,6 +556,7 @@ public sealed class MxAccessSession : IDisposable
/// Unsubscribes from multiple items in bulk, returning success/failure results.
/// Handle returned by the worker.
/// Enumerable of item handles to unsubscribe from.
+ /// Per-item success or failure results in the same order as .
public IReadOnlyList UnsubscribeBulk(
int serverHandle,
IEnumerable itemHandles)
@@ -596,6 +608,7 @@ public sealed class MxAccessSession : IDisposable
/// The MXAccess server handle.
/// The write entries to process.
/// Converts protobuf MxValue to COM-compatible variant.
+ /// Per-entry write results; failures are captured rather than thrown.
public IReadOnlyList WriteBulk(
int serverHandle,
IReadOnlyList entries,
@@ -628,6 +641,7 @@ public sealed class MxAccessSession : IDisposable
/// The MXAccess server handle.
/// The write2 entries to process.
/// Converts protobuf MxValue to COM-compatible variant.
+ /// Per-entry write results; failures are captured rather than thrown.
public IReadOnlyList Write2Bulk(
int serverHandle,
IReadOnlyList entries,
@@ -665,6 +679,7 @@ public sealed class MxAccessSession : IDisposable
/// The MXAccess server handle.
/// The WriteSecured entries to process.
/// Converts protobuf MxValue to COM-compatible variant.
+ /// Per-entry write results; failures are captured rather than thrown.
public IReadOnlyList WriteSecuredBulk(
int serverHandle,
IReadOnlyList entries,
@@ -702,6 +717,7 @@ public sealed class MxAccessSession : IDisposable
/// The MXAccess server handle.
/// The WriteSecured2 entries to process.
/// Converts protobuf MxValue to COM-compatible variant.
+ /// Per-entry write results; failures are captured rather than thrown.
public IReadOnlyList WriteSecured2Bulk(
int serverHandle,
IReadOnlyList entries,
@@ -750,6 +766,7 @@ public sealed class MxAccessSession : IDisposable
/// The tag addresses to read.
/// The timeout per tag.
/// Action invoked on each poll iteration.
+ /// Per-tag read results including value, quality, and status.
public IReadOnlyList ReadBulk(
int serverHandle,
IReadOnlyList tagAddresses,
@@ -991,6 +1008,7 @@ public sealed class MxAccessSession : IDisposable
}
/// Gracefully shuts down the session, cleaning up all handles.
+ /// A result containing any cleanup failures encountered during shutdown.
public MxAccessShutdownResult ShutdownGracefully()
{
if (disposed)
@@ -1008,7 +1026,7 @@ public sealed class MxAccessSession : IDisposable
return new MxAccessShutdownResult(failures);
}
- /// Releases the MXAccess COM object and resources.
+ ///
public void Dispose()
{
if (disposed)
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessStaSession.cs b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessStaSession.cs
index cd8448b..49f23cf 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessStaSession.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessStaSession.cs
@@ -168,13 +168,7 @@ public sealed class MxAccessStaSession : IWorkerRuntimeSession
return StartAsync(string.Empty, workerProcessId, cancellationToken);
}
- ///
- /// Starts the MXAccess COM session with a session ID asynchronously.
- ///
- /// Session identifier.
- /// Worker process identifier.
- /// Cancellation token.
- /// Worker ready message.
+ ///
public async Task StartAsync(
string sessionId,
int workerProcessId,
@@ -368,11 +362,7 @@ public sealed class MxAccessStaSession : IWorkerRuntimeSession
return fault;
}
- ///
- /// Dispatches a command to the STA thread for execution asynchronously.
- ///
- /// The command to dispatch.
- /// Command reply.
+ ///
public Task DispatchAsync(StaCommand command)
{
if (commandDispatcher is null)
@@ -383,10 +373,7 @@ public sealed class MxAccessStaSession : IWorkerRuntimeSession
return commandDispatcher.DispatchAsync(command);
}
- ///
- /// Captures a heartbeat snapshot of the session's runtime state.
- ///
- /// Heartbeat snapshot.
+ ///
public WorkerRuntimeHeartbeatSnapshot CaptureHeartbeat()
{
uint pendingCommandCount = 0;
@@ -406,38 +393,25 @@ public sealed class MxAccessStaSession : IWorkerRuntimeSession
currentCommandCorrelationId);
}
- ///
- /// Requests graceful shutdown of the command dispatcher.
- ///
+ ///
public void RequestShutdown()
{
commandDispatcher?.RequestShutdown();
}
- ///
- /// Drains up to the specified number of events from the queue.
- ///
- /// Maximum events to drain.
- /// Drained events.
+ ///
public IReadOnlyList DrainEvents(uint maxEvents)
{
return eventQueue.Drain(maxEvents);
}
- ///
- /// Drains a fault from the queue if present.
- ///
- /// Drained fault or null.
+ ///
public WorkerFault? DrainFault()
{
return eventQueue.DrainFault();
}
- ///
- /// Cancels a queued command by correlation ID.
- ///
- /// Correlation ID of the command to cancel.
- /// True if cancelled; otherwise false.
+ ///
public bool CancelCommand(string correlationId)
{
return commandDispatcher?.CancelQueuedCommand(correlationId) ?? false;
@@ -497,12 +471,7 @@ public sealed class MxAccessStaSession : IWorkerRuntimeSession
cancellationToken);
}
- ///
- /// Performs graceful shutdown of the MXAccess session within a timeout.
- ///
- /// Maximum time allowed for shutdown.
- /// Cancellation token.
- /// Shutdown result with any cleanup failures.
+ ///
public async Task ShutdownGracefullyAsync(
TimeSpan timeout,
CancellationToken cancellationToken = default)
@@ -610,7 +579,7 @@ public sealed class MxAccessStaSession : IWorkerRuntimeSession
return result;
}
- /// Releases resources and shuts down the session.
+ ///
public void Dispose()
{
if (disposed)
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessValueCache.cs b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessValueCache.cs
index 7bba593..bc9b366 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessValueCache.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/MxAccessValueCache.cs
@@ -60,6 +60,7 @@ public sealed class MxAccessValueCache
/// MXAccess server handle.
/// MXAccess item handle.
/// The cached value if found.
+ /// True if a cached entry exists; otherwise false.
public bool TryGet(
int serverHandle,
int itemHandle,
@@ -102,6 +103,7 @@ public sealed class MxAccessValueCache
/// Action that pumps any pending Windows messages.
/// The cached value if the update was received before the deadline.
/// How long to sleep between pump cycles. Default 5 ms.
+ /// True if a new value arrived before the deadline; false if the deadline elapsed.
public bool TryWaitForUpdate(
int serverHandle,
int itemHandle,
@@ -137,6 +139,7 @@ public sealed class MxAccessValueCache
/// Returns the current version for a handle pair, or 0 if no entry exists.
/// MXAccess server handle.
/// MXAccess item handle.
+ /// The current version counter, or 0 if no entry is cached.
public ulong CurrentVersion(
int serverHandle,
int itemHandle)
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/WnWrapAlarmConsumer.cs b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/WnWrapAlarmConsumer.cs
index 250cc97..77015b2 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/WnWrapAlarmConsumer.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/MxAccess/WnWrapAlarmConsumer.cs
@@ -86,7 +86,7 @@ public sealed class WnWrapAlarmConsumer : IMxAccessAlarmConsumer
: DefaultMaxAlarmsPerFetch;
}
- ///
+ /// Raised when a new alarm transition is detected during a poll cycle.
public event EventHandler? AlarmTransitionEmitted;
///
@@ -297,15 +297,7 @@ public sealed class WnWrapAlarmConsumer : IMxAccessAlarmConsumer
}
}
- ///
- /// Synchronously poll the wnwrap consumer once and dispatch any
- /// transitions. STA-bound hosts drive polling by calling this from
- /// the thread that owns the COM object. The consumer deliberately
- /// owns no internal timer: a thread-pool timer would call the
- /// apartment-threaded COM object off its owning STA and can block
- /// indefinitely on cross-apartment marshaling when the STA is not
- /// pumping messages.
- ///
+ ///
public void PollOnce()
{
wwAlarmConsumerClass? com;
@@ -396,6 +388,7 @@ public sealed class WnWrapAlarmConsumer : IMxAccessAlarmConsumer
/// resync).
///
/// The XML snapshot payload.
+ /// A GUID-keyed dictionary of snapshot alarm records.
public static Dictionary ParseSnapshotXml(string xml)
{
Dictionary records =
@@ -460,6 +453,7 @@ public sealed class WnWrapAlarmConsumer : IMxAccessAlarmConsumer
///
/// The 32-character hex GUID string.
/// The parsed GUID, or Empty if parsing fails.
+ /// true if parsing succeeded; otherwise false.
public static bool TryParseHexGuid(string? hex, out Guid guid)
{
guid = Guid.Empty;
@@ -487,6 +481,7 @@ public sealed class WnWrapAlarmConsumer : IMxAccessAlarmConsumer
/// so the worker doesn't fail to start.
///
/// The subscription expression.
+ /// The XML alarm query string for SetXmlAlarmQuery.
internal static string ComposeXmlAlarmQuery(string subscription)
{
string node = Environment.MachineName;
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/Sta/StaComApartmentInitializer.cs b/src/ZB.MOM.WW.MxGateway.Worker/Sta/StaComApartmentInitializer.cs
index ca332db..3d40b4b 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/Sta/StaComApartmentInitializer.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/Sta/StaComApartmentInitializer.cs
@@ -9,7 +9,7 @@ public sealed class StaComApartmentInitializer : IStaComApartmentInitializer
private const int SOk = 0;
private const int SFalse = 1;
- /// Initializes the COM apartment in single-threaded mode.
+ ///
public void Initialize()
{
int hresult = CoInitializeEx(IntPtr.Zero, CoInitializeApartmentThreaded);
@@ -19,7 +19,7 @@ public sealed class StaComApartmentInitializer : IStaComApartmentInitializer
}
}
- /// Uninitializes the COM apartment.
+ ///
public void Uninitialize()
{
CoUninitialize();
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/Sta/StaMessagePump.cs b/src/ZB.MOM.WW.MxGateway.Worker/Sta/StaMessagePump.cs
index 3284aa3..685a16c 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/Sta/StaMessagePump.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/Sta/StaMessagePump.cs
@@ -43,6 +43,7 @@ public sealed class StaMessagePump
}
/// Pumps and dispatches all pending Windows messages, returning the count processed.
+ /// The number of Windows messages dispatched.
public int PumpPendingMessages()
{
int pumpedMessages = 0;
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/Sta/StaRuntime.cs b/src/ZB.MOM.WW.MxGateway.Worker/Sta/StaRuntime.cs
index 3f90b7f..98793b3 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/Sta/StaRuntime.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/Sta/StaRuntime.cs
@@ -86,6 +86,7 @@ public sealed class StaRuntime : IDisposable
/// wait. Callers must already be on the STA; the method is otherwise
/// safe (PeekMessage simply finds no messages).
///
+ /// The number of Windows messages dispatched.
public int PumpPendingMessages() => messagePump.PumpPendingMessages();
///
@@ -212,9 +213,7 @@ public sealed class StaRuntime : IDisposable
return stopped;
}
- ///
- /// Releases resources used by the STA runtime.
- ///
+ ///
public void Dispose()
{
if (disposed)
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/Sta/StaWorkItem.cs b/src/ZB.MOM.WW.MxGateway.Worker/Sta/StaWorkItem.cs
index e7d7504..8861236 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/Sta/StaWorkItem.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/Sta/StaWorkItem.cs
@@ -41,7 +41,7 @@ internal sealed class StaWorkItem : IStaWorkItem
private TaskCompletionSource Completion { get; }
- /// Cancels the work item before execution begins.
+ ///
public void CancelBeforeExecution()
{
if (Interlocked.CompareExchange(ref started, 1, 0) == 0)
@@ -51,7 +51,7 @@ internal sealed class StaWorkItem : IStaWorkItem
}
}
- /// Executes the work item command.
+ ///
public void Execute()
{
if (Interlocked.CompareExchange(ref started, 1, 0) != 0)
diff --git a/src/ZB.MOM.WW.MxGateway.Worker/WorkerApplication.cs b/src/ZB.MOM.WW.MxGateway.Worker/WorkerApplication.cs
index d253d86..1573c7f 100644
--- a/src/ZB.MOM.WW.MxGateway.Worker/WorkerApplication.cs
+++ b/src/ZB.MOM.WW.MxGateway.Worker/WorkerApplication.cs
@@ -11,6 +11,7 @@ public static class WorkerApplication
{
/// Initializes and runs the worker with default environment and logging.
/// Command-line arguments.
+ /// The worker exit code.
public static int Run(string[] args)
{
return Run(
@@ -23,6 +24,7 @@ public static class WorkerApplication
/// Command-line arguments.
/// Worker environment for resolving configuration.
/// Worker logger for diagnostics.
+ /// The worker exit code.
public static int Run(
string[] args,
IWorkerEnvironment environment,
@@ -40,6 +42,7 @@ public static class WorkerApplication
/// Worker environment for resolving configuration.
/// Worker logger for diagnostics.
/// Named pipe client for gateway communication.
+ /// The worker exit code.
public static int Run(
string[] args,
IWorkerEnvironment environment,