Add XML documentation across gateway, worker, and .NET client

This commit is contained in:
Joseph Doherty
2026-04-30 11:49:58 -04:00
parent 4731ab535c
commit eed1e88a37
269 changed files with 4555 additions and 13 deletions
@@ -21,6 +21,9 @@ public sealed class GatewayEndToEndFakeWorkerSmokeTests
private const int ServerHandle = 1001;
private const int ItemHandle = 2002;
/// <summary>
/// Verifies gateway session lifecycle with a scripted fake worker: open, command, event, close.
/// </summary>
[Fact]
public async Task GatewayService_WithFakeWorker_CompletesSessionCommandEventAndClosePath()
{
@@ -146,6 +149,10 @@ public sealed class GatewayEndToEndFakeWorkerSmokeTests
private readonly GatewayMetrics _metrics = new();
private readonly SessionRegistry _registry = new();
/// <summary>
/// Initializes a new instance of <see cref="GatewayServiceFixture"/>.
/// </summary>
/// <param name="launcher">Worker process launcher for the fixture.</param>
public GatewayServiceFixture(IWorkerProcessLauncher launcher)
{
IOptions<GatewayOptions> options = Options.Create(CreateOptions());
@@ -178,8 +185,14 @@ public sealed class GatewayEndToEndFakeWorkerSmokeTests
NullLogger<MxAccessGatewayService>.Instance);
}
/// <summary>
/// Gets the configured gateway service instance.
/// </summary>
public MxAccessGatewayService Service { get; }
/// <summary>
/// Disposes all active sessions and metrics.
/// </summary>
public async ValueTask DisposeAsync()
{
foreach (GatewaySession session in _registry.Snapshot())
@@ -220,12 +233,27 @@ public sealed class GatewayEndToEndFakeWorkerSmokeTests
public const int ProcessId = 4680;
private readonly ConcurrentQueue<MxCommandKind> _commandKinds = new();
/// <summary>
/// Gets the fake worker process instance.
/// </summary>
public FakeWorkerProcess Process { get; } = new(ProcessId);
/// <summary>
/// Gets the collection of command kinds processed by the worker.
/// </summary>
public IReadOnlyCollection<MxCommandKind> CommandKinds => _commandKinds.ToArray();
/// <summary>
/// Gets the worker's asynchronous task.
/// </summary>
public Task WorkerTask { get; private set; } = Task.CompletedTask;
/// <summary>
/// Launches a new worker process and returns a handle to manage it.
/// </summary>
/// <param name="request">Worker process launch request parameters.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>Worker process handle.</returns>
public Task<WorkerProcessHandle> LaunchAsync(
WorkerProcessLaunchRequest request,
CancellationToken cancellationToken = default)
@@ -321,12 +349,26 @@ public sealed class GatewayEndToEndFakeWorkerSmokeTests
private sealed class FakeWorkerProcess(int processId) : IWorkerProcess
{
/// <summary>
/// Gets the process identifier.
/// </summary>
public int Id { get; } = processId;
/// <summary>
/// Gets a value indicating whether the process has exited.
/// </summary>
public bool HasExited { get; private set; }
/// <summary>
/// Gets the exit code of the process.
/// </summary>
public int? ExitCode { get; private set; }
/// <summary>
/// Waits for the process to exit asynchronously.
/// </summary>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>Completed task.</returns>
public ValueTask WaitForExitAsync(CancellationToken cancellationToken)
{
HasExited = true;
@@ -334,15 +376,26 @@ public sealed class GatewayEndToEndFakeWorkerSmokeTests
return ValueTask.CompletedTask;
}
/// <summary>
/// Terminates the process.
/// </summary>
/// <param name="entireProcessTree">Whether to kill the entire process tree.</param>
public void Kill(bool entireProcessTree)
{
MarkExited(-1);
}
/// <summary>
/// Releases resources used by this process.
/// </summary>
public void Dispose()
{
}
/// <summary>
/// Marks the process as exited with the specified exit code.
/// </summary>
/// <param name="exitCode">The process exit code.</param>
public void MarkExited(int exitCode)
{
HasExited = true;
@@ -356,6 +409,9 @@ public sealed class GatewayEndToEndFakeWorkerSmokeTests
private readonly TaskCompletionSource<T> _firstMessage = new(TaskCreationOptions.RunContinuationsAsynchronously);
private readonly List<T> _messages = [];
/// <summary>
/// Gets the recorded messages written to this stream.
/// </summary>
public IReadOnlyList<T> Messages
{
get
@@ -367,8 +423,16 @@ public sealed class GatewayEndToEndFakeWorkerSmokeTests
}
}
/// <summary>
/// Gets or sets options for writing messages to the stream.
/// </summary>
public WriteOptions? WriteOptions { get; set; }
/// <summary>
/// Writes a message to the stream asynchronously.
/// </summary>
/// <param name="message">The message to write.</param>
/// <returns>Completed task.</returns>
public Task WriteAsync(T message)
{
lock (_syncRoot)
@@ -380,6 +444,11 @@ public sealed class GatewayEndToEndFakeWorkerSmokeTests
return Task.CompletedTask;
}
/// <summary>
/// Waits for the first message to be written within the specified timeout.
/// </summary>
/// <param name="timeout">Maximum time to wait for the first message.</param>
/// <returns>The first message written to this stream.</returns>
public async Task<T> WaitForFirstMessageAsync(TimeSpan timeout)
{
return await _firstMessage.Task.WaitAsync(timeout).ConfigureAwait(false);
@@ -394,43 +463,66 @@ public sealed class GatewayEndToEndFakeWorkerSmokeTests
private Status _status;
private WriteOptions? _writeOptions;
/// <inheritdoc />
protected override string MethodCore => "/mxaccess_gateway.v1.MxAccessGateway/Test";
/// <inheritdoc />
protected override string HostCore => "localhost";
/// <inheritdoc />
protected override string PeerCore => "ipv4:127.0.0.1:5000";
/// <inheritdoc />
protected override DateTime DeadlineCore => DateTime.UtcNow.AddMinutes(1);
/// <inheritdoc />
protected override Metadata RequestHeadersCore => _requestHeaders;
/// <inheritdoc />
protected override CancellationToken CancellationTokenCore => cancellationToken;
/// <inheritdoc />
protected override Metadata ResponseTrailersCore => _responseTrailers;
/// <inheritdoc />
protected override Status StatusCore
{
get => _status;
set => _status = value;
}
/// <inheritdoc />
protected override WriteOptions? WriteOptionsCore
{
get => _writeOptions;
set => _writeOptions = value;
}
/// <inheritdoc />
protected override AuthContext AuthContextCore { get; } = new(
string.Empty,
new Dictionary<string, List<AuthProperty>>(StringComparer.Ordinal));
/// <inheritdoc />
protected override IDictionary<object, object> UserStateCore => _userState;
/// <summary>
/// Writes response headers asynchronously.
/// </summary>
/// <param name="responseHeaders">Headers to write.</param>
/// <returns>Completed task.</returns>
/// <inheritdoc />
protected override Task WriteResponseHeadersAsyncCore(Metadata responseHeaders)
{
return Task.CompletedTask;
}
/// <summary>
/// Creates a context propagation token with the specified options.
/// </summary>
/// <param name="options">Propagation options.</param>
/// <returns>Propagation token.</returns>
/// <inheritdoc />
protected override ContextPropagationToken CreatePropagationTokenCore(
ContextPropagationOptions? options)
{