docs: backfill XML documentation across 756 files
v2-ci / build (push) Failing after 1m43s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (push) Has been skipped

Adds <summary>, <param>, <typeparam>, and <inheritdoc/> tags to public
members surfaced by commentchecker — resolves 5,847 of 5,869 issues
(99.6%) across three /fixdocs passes.
This commit is contained in:
Joseph Doherty
2026-05-28 08:10:17 -04:00
parent f9fc7dd2e1
commit 64e3fbe035
756 changed files with 9876 additions and 96 deletions
@@ -48,26 +48,35 @@ namespace ZB.MOM.WW.OtOpcUa.Host.IntegrationTests;
public sealed class TwoNodeClusterHarness : IAsyncDisposable
{
public const string TestRoles = "admin,driver";
/// <summary>Gets the shared database name for both cluster nodes.</summary>
public string SharedDbName { get; } = $"two-node-cluster-{Guid.NewGuid():N}";
/// <summary>Gets the harness mode configuration from environment variables.</summary>
public HarnessMode Mode { get; } = HarnessMode.FromEnvironment();
private string? _sqlDbName;
private string? _sqlConnString;
/// <summary>Gets the first web application node.</summary>
public WebApplication NodeA { get; private set; } = null!;
/// <summary>Gets the second web application node.</summary>
public WebApplication NodeB { get; private set; } = null!;
/// <summary>Gets the Akka port allocated for node A.</summary>
public int NodeAAkkaPort { get; private set; }
/// <summary>Gets the Akka port allocated for node B.</summary>
public int NodeBAkkaPort { get; private set; }
// Both nodes bind to 127.0.0.1 — ClusterRoleInfo + ConfigPublishCoordinator encode
// host:port into NodeId so the cluster membership stays distinct on different ports.
public const string LoopbackHost = "127.0.0.1";
/// <summary>Gets the Akka ActorSystem for node A.</summary>
public ActorSystem NodeASystem => NodeA.Services.GetRequiredService<ActorSystem>();
/// <summary>Gets the Akka ActorSystem for node B.</summary>
public ActorSystem NodeBSystem => NodeB.Services.GetRequiredService<ActorSystem>();
/// <summary>Boots both nodes and waits up to <paramref name="formationTimeout"/> for cluster convergence.</summary>
/// <param name="formationTimeout">Maximum time to wait for cluster formation; defaults to 20 seconds if not provided.</param>
public static async Task<TwoNodeClusterHarness> StartAsync(TimeSpan? formationTimeout = null)
{
var harness = new TwoNodeClusterHarness();
@@ -110,6 +119,7 @@ public sealed class TwoNodeClusterHarness : IAsyncDisposable
/// Rebuilds node B on the same Akka port + same ConfigDb and waits for the cluster
/// to re-converge to 2 Up members. Use after <see cref="StopNodeBAsync"/> to test rejoin.
/// </summary>
/// <param name="formationTimeout">The maximum time to wait for cluster formation; defaults to 20 seconds.</param>
public async Task RestartNodeBAsync(TimeSpan? formationTimeout = null)
{
NodeB = await BuildNodeAsync(this, NodeRole.Joiner);
@@ -124,6 +134,8 @@ public sealed class TwoNodeClusterHarness : IAsyncDisposable
/// Waits for node A's cluster view to reach <paramref name="expectedUpMembers"/> members in
/// <see cref="MemberStatus.Up"/>. Used for asserting shrink-after-stop or grow-after-restart.
/// </summary>
/// <param name="expectedUpMembers">The expected number of Up members in the cluster.</param>
/// <param name="timeout">The maximum time to wait for the expected cluster size.</param>
public async Task WaitForClusterSizeAsync(int expectedUpMembers, TimeSpan timeout)
{
var deadline = DateTime.UtcNow + timeout;
@@ -265,6 +277,7 @@ public sealed class TwoNodeClusterHarness : IAsyncDisposable
return port;
}
/// <summary>Asynchronously disposes both nodes and cleans up the SQL database if used.</summary>
public async ValueTask DisposeAsync()
{
if (NodeB is not null) await NodeB.DisposeAsync();
@@ -279,6 +292,8 @@ public sealed class TwoNodeClusterHarness : IAsyncDisposable
/// <summary>Captures the env-var driven harness mode at construction time.</summary>
public sealed record HarnessMode(bool UseSqlServer, bool UseRealLdap)
{
/// <summary>Creates a HarnessMode from environment variable settings.</summary>
/// <returns>A HarnessMode configured from OTOPCUA_HARNESS_USE_SQL and OTOPCUA_HARNESS_USE_LDAP environment variables.</returns>
public static HarnessMode FromEnvironment() => new(
UseSqlServer: Environment.GetEnvironmentVariable("OTOPCUA_HARNESS_USE_SQL") == "1",
UseRealLdap: Environment.GetEnvironmentVariable("OTOPCUA_HARNESS_USE_LDAP") == "1");
@@ -286,6 +301,11 @@ public sealed class TwoNodeClusterHarness : IAsyncDisposable
private sealed class StubLdapAuthService : ILdapAuthService
{
/// <summary>Asynchronously authenticates a user with the stub LDAP service.</summary>
/// <param name="username">The username to authenticate.</param>
/// <param name="password">The password to authenticate against.</param>
/// <param name="ct">The cancellation token.</param>
/// <returns>A task that returns the LDAP authentication result.</returns>
public Task<LdapAuthResult> AuthenticateAsync(string username, string password, CancellationToken ct = default)
=> Task.FromResult(new LdapAuthResult(
Success: password == "valid-password",