docs(tests): fix CommentChecker findings across tests/ — 13,392 → 0 (repo-wide scan clean)

Comment/XML-doc changes only:
- add summaries to ~10k test methods, fixtures, fakes and helpers
  (+ <param> on theories, <returns> on async Task methods,
  <inheritdoc/> on interface implementations the checker can resolve)
- strip ~2.6k project-tracking references (WP*, P*-*, row-NN, Task N,
  #NN, Component-0NN) from comments, keeping the explanatory text;
  reword false positives in comments only
- real docs on fakes implementing BCL/library interfaces
  (IDisposable, ILogger, IOptionsMonitor, IAsyncLifetime)
- reword the last 5 src/ false positives (CWE-1236, failures-1,
  year-0001, M365)

Only non-comment edits: four one-line nested classes split across lines
so members can carry docs. Build 0 errors / 0 warnings.
This commit is contained in:
Joseph Doherty
2026-10-07 15:05:49 -04:00
parent 0ffd4bdbea
commit 513fa1aa16
998 changed files with 17896 additions and 2395 deletions
@@ -45,6 +45,8 @@ namespace ZB.MOM.WW.ScadaBridge.Host.Tests;
/// </summary>
internal static class AkkaHostedServiceRemover
{
/// <summary>Removes only the Akka hosted service registration, leaving the Akka services resolvable.</summary>
/// <param name="services">The service collection to modify.</param>
internal static void RemoveAkkaHostedServiceOnly(IServiceCollection services)
{
// Pattern used in Program.cs:
@@ -88,6 +90,7 @@ public class CentralCompositionRootTests : IDisposable
private readonly string? _previousEnv;
private readonly CentralDbTestEnvironment _dbEnv;
/// <summary>Initializes the tests by booting the central composition root with test configuration.</summary>
public CentralCompositionRootTests()
{
_previousEnv = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT");
@@ -114,7 +117,7 @@ public class CentralCompositionRootTests : IDisposable
["ScadaBridge:Cluster:SeedNodes:1"] = "akka.tcp://scadabridge@localhost:2552",
["ScadaBridge:Database:SkipMigrations"] = "true",
["ScadaBridge:Security:JwtSigningKey"] = "test-signing-key-must-be-at-least-32-chars-long!",
// Task 1.4: LDAP settings nest under Security:Ldap (shared LdapOptions).
// LDAP settings nest under Security:Ldap (shared LdapOptions).
// ServiceAccountDn is now required by the library's LdapOptionsValidator
// (ValidateOnStart), so it must be present for the host to start.
["ScadaBridge:Security:Ldap:Server"] = "localhost",
@@ -159,6 +162,7 @@ public class CentralCompositionRootTests : IDisposable
_ = _factory.Server;
}
/// <summary>Disposes the web application factory and restores the environment variables.</summary>
public void Dispose()
{
// try/finally: a throwing host teardown must not strand the process-wide
@@ -176,6 +180,8 @@ public class CentralCompositionRootTests : IDisposable
// --- Singletons ---
/// <summary>Verifies that the service resolves as a singleton from the central composition root.</summary>
/// <param name="serviceType">The service type to resolve.</param>
[Theory]
[MemberData(nameof(CentralSingletonServices))]
public void Central_ResolveSingleton(Type serviceType)
@@ -184,6 +190,7 @@ public class CentralCompositionRootTests : IDisposable
Assert.NotNull(service);
}
/// <summary>Gets the service types expected to resolve as singletons on the central node.</summary>
public static IEnumerable<object[]> CentralSingletonServices => new[]
{
new object[] { typeof(CommunicationService) },
@@ -194,12 +201,14 @@ public class CentralCompositionRootTests : IDisposable
new object[] { typeof(OAuth2TokenService) },
new object[] { typeof(InboundScriptExecutor) },
// Security: the shared ZB.MOM.WW.Auth.Ldap service is registered as a stateless
// singleton by AddZbLdapAuth (Task 1.2), replacing the old scoped LdapAuthService.
// singleton by AddZbLdapAuth, replacing the old scoped LdapAuthService.
new object[] { typeof(ILdapAuthService) },
};
// --- Scoped services ---
/// <summary>Verifies that the service resolves from a scope in the central composition root.</summary>
/// <param name="serviceType">The service type to resolve.</param>
[Theory]
[MemberData(nameof(CentralScopedServices))]
public void Central_ResolveScoped(Type serviceType)
@@ -209,6 +218,7 @@ public class CentralCompositionRootTests : IDisposable
Assert.NotNull(service);
}
/// <summary>Gets the service types expected to resolve as scoped services on the central node.</summary>
public static IEnumerable<object[]> CentralScopedServices => new[]
{
// TemplateEngine
@@ -235,7 +245,7 @@ public class CentralCompositionRootTests : IDisposable
new object[] { typeof(IDatabaseGateway) },
// NotificationService — central-only SMTP primitives. The orphan
// NotificationDeliveryService + INotificationDeliveryService were removed
// (NS-019) when sites stopped delivering notifications; the central
// when sites stopped delivering notifications; the central
// EmailNotificationDeliveryAdapter is now the only resolver of these
// primitives.
new object[] { typeof(Func<ISmtpClientWrapper>) },
@@ -258,6 +268,8 @@ public class CentralCompositionRootTests : IDisposable
// --- Transient services ---
/// <summary>Verifies that the service resolves as a transient from the central composition root.</summary>
/// <param name="serviceType">The service type to resolve.</param>
[Theory]
[MemberData(nameof(CentralTransientServices))]
public void Central_ResolveTransient(Type serviceType)
@@ -267,6 +279,7 @@ public class CentralCompositionRootTests : IDisposable
Assert.NotNull(service);
}
/// <summary>Gets the service types expected to resolve as transient services on the central node.</summary>
public static IEnumerable<object[]> CentralTransientServices => new[]
{
new object[] { typeof(FlatteningService) },
@@ -279,6 +292,8 @@ public class CentralCompositionRootTests : IDisposable
// --- Options ---
/// <summary>Verifies that the options type resolves from the central composition root.</summary>
/// <param name="optionsType">The options type to resolve.</param>
[Theory]
[MemberData(nameof(CentralOptions))]
public void Central_ResolveOptions(Type optionsType)
@@ -287,6 +302,7 @@ public class CentralCompositionRootTests : IDisposable
Assert.NotNull(service);
}
/// <summary>Gets the options types expected to be registered on the central node.</summary>
public static IEnumerable<object[]> CentralOptions => new[]
{
new object[] { typeof(IOptions<NodeOptions>) },
@@ -304,6 +320,7 @@ public class CentralCompositionRootTests : IDisposable
// --- Hosted services ---
/// <summary>Verifies that the central health aggregator is registered as a hosted service.</summary>
[Fact]
public void Central_CentralHealthAggregator_RegisteredAsHostedService()
{
@@ -311,10 +328,10 @@ public class CentralCompositionRootTests : IDisposable
Assert.Contains(hostedServices, s => s.GetType() == typeof(CentralHealthAggregator));
}
// --- InboundAPI-022 regression ---
// --- Active-node gate regression ---
/// <summary>
/// InboundAPI-022 regression: the Central composition root MUST register a
/// Regression test: the Central composition root MUST register a
/// concrete <see cref="IActiveNodeGate"/> implementation. Without it,
/// <see cref="InboundApiEndpointFilter"/> falls through to "allow" and a
/// standby central node continues to serve the inbound API, racing the
@@ -348,6 +365,7 @@ public class CentralCompositionRootTests : IDisposable
/// the gap is invisible until the graph is actually built — the same defect class as the
/// four caught in the secrets library itself.
/// </summary>
/// <param name="serviceType">The Secrets.Ui component dependency type to resolve.</param>
[Theory]
[InlineData(typeof(ZB.MOM.WW.Secrets.Abstractions.ISecretStore))]
[InlineData(typeof(ZB.MOM.WW.Secrets.Abstractions.ISecretCipher))]
@@ -384,6 +402,7 @@ public class CentralCompositionRootTests : IDisposable
Assert.Null(_factory.Services.GetService<IInboundApiKeyStoreImporter>());
}
/// <summary>Verifies that the shared audit seam resolves to the central direct-write bridge.</summary>
[Fact]
public void Central_SharedAuditSeam_IsTheCentralDirectWriteBridge()
{
@@ -508,11 +527,13 @@ public class CentralSqlServerKeyStoreCompositionRootTests : IDisposable
_ = _factory.Server;
}
/// <summary>Initializes the tests by booting the central composition root with the SQL Server key store provider.</summary>
public CentralSqlServerKeyStoreCompositionRootTests()
: this(explicitConnectionString: null)
{
}
/// <summary>Disposes the web application factory and restores the environment variables.</summary>
public void Dispose()
{
try
@@ -528,6 +549,9 @@ public class CentralSqlServerKeyStoreCompositionRootTests : IDisposable
}
}
/// <summary>Verifies that the SQL Server provider resolves the shared stores to their SQL Server implementations.</summary>
/// <param name="serviceType">The service type to resolve.</param>
/// <param name="expectedImplementation">The implementation type expected for the service.</param>
[Theory]
[InlineData(typeof(ZB.MOM.WW.Auth.Abstractions.ApiKeys.IApiKeyStore),
typeof(ZB.MOM.WW.Auth.ApiKeys.SqlServer.SqlServerApiKeyStore))]
@@ -583,6 +607,7 @@ public class CentralSqlServerKeyStoreCompositionRootTests : IDisposable
public sealed class CentralSqlServerKeyStoreExplicitConnectionStringTests
: CentralSqlServerKeyStoreCompositionRootTests
{
/// <summary>Initializes the tests with an explicit key store connection string.</summary>
public CentralSqlServerKeyStoreExplicitConnectionStringTests()
: base(ExplicitConnectionString)
{
@@ -613,6 +638,7 @@ public class SiteCompositionRootTests : IDisposable
private readonly string _tempTrackingDbPath;
private readonly string _tempLocalDbPath;
/// <summary>Initializes the tests with temporary database paths for the site composition root.</summary>
public SiteCompositionRootTests()
{
_tempDbPath = Path.Combine(Path.GetTempPath(), $"scadabridge_test_{Guid.NewGuid()}.db");
@@ -655,6 +681,7 @@ public class SiteCompositionRootTests : IDisposable
_host = builder.Build();
}
/// <summary>Disposes the host and deletes the temporary database files, ignoring failures.</summary>
public void Dispose()
{
(_host as IDisposable)?.Dispose();
@@ -663,6 +690,7 @@ public class SiteCompositionRootTests : IDisposable
try { File.Delete(_tempLocalDbPath); } catch { /* best effort */ }
}
/// <summary>Verifies that the operation tracking store resolves on a site node.</summary>
[Fact]
public void Site_Resolves_IOperationTrackingStore()
{
@@ -678,6 +706,8 @@ public class SiteCompositionRootTests : IDisposable
// --- Singletons ---
/// <summary>Verifies that the service resolves as a singleton from the site composition root.</summary>
/// <param name="serviceType">The service type to resolve.</param>
[Theory]
[MemberData(nameof(SiteSingletonServices))]
public void Site_ResolveSingleton(Type serviceType)
@@ -686,6 +716,7 @@ public class SiteCompositionRootTests : IDisposable
Assert.NotNull(service);
}
/// <summary>Gets the service types expected to resolve as singletons on a site node.</summary>
public static IEnumerable<object[]> SiteSingletonServices => new[]
{
new object[] { typeof(CommunicationService) },
@@ -703,15 +734,16 @@ public class SiteCompositionRootTests : IDisposable
new object[] { typeof(IEventLogQueryService) },
new object[] { typeof(ISiteIdentityProvider) },
new object[] { typeof(IHealthReportTransport) },
// M2.15 (#29): the active-node check must be registered on site nodes so
// EventLogPurge's log line can report whether this node is active (arch-review
// 2026-08-19 P4-4: it no longer gates which node purges — every node purges its
// own site_events file).
// The active-node check must be registered on site nodes so
// EventLogPurge's log line can report whether this node is active (it no
// longer gates which node purges — every node purges its own site_events file).
new object[] { typeof(SiteEventLogActiveNodeCheck) },
};
// --- Scoped services ---
/// <summary>Verifies that the service resolves from a scope in the site composition root.</summary>
/// <param name="serviceType">The service type to resolve.</param>
[Theory]
[MemberData(nameof(SiteScopedServices))]
public void Site_ResolveScoped(Type serviceType)
@@ -721,11 +753,12 @@ public class SiteCompositionRootTests : IDisposable
Assert.NotNull(service);
}
/// <summary>Gets the service types expected to resolve as scoped services on a site node.</summary>
public static IEnumerable<object[]> SiteScopedServices => new[]
{
new object[] { typeof(IExternalSystemRepository) },
// INotificationRepository is intentionally absent — notification config is
// central-only (arch-review 08 §1.3/#23); the site-side variant was removed.
// central-only; the site-side variant was removed.
new object[] { typeof(ExternalSystemClient) },
new object[] { typeof(IExternalSystemClient) },
new object[] { typeof(DatabaseGateway) },
@@ -734,6 +767,7 @@ public class SiteCompositionRootTests : IDisposable
// --- Implementation type assertions ---
/// <summary>Verifies that the external system repository resolves to the site implementation.</summary>
[Fact]
public void Site_ExternalSystemRepository_IsSiteImplementation()
{
@@ -742,6 +776,7 @@ public class SiteCompositionRootTests : IDisposable
Assert.IsType<SiteExternalSystemRepository>(repo);
}
/// <summary>Verifies that the notification repository is not registered on a site node.</summary>
[Fact]
public void Site_NotificationRepository_IsNotRegistered()
{
@@ -756,6 +791,8 @@ public class SiteCompositionRootTests : IDisposable
// --- Options ---
/// <summary>Verifies that the options type resolves from the site composition root.</summary>
/// <param name="optionsType">The options type to resolve.</param>
[Theory]
[MemberData(nameof(SiteOptions))]
public void Site_ResolveOptions(Type optionsType)
@@ -764,6 +801,7 @@ public class SiteCompositionRootTests : IDisposable
Assert.NotNull(service);
}
/// <summary>Gets the options types expected to be registered on a site node.</summary>
public static IEnumerable<object[]> SiteOptions => new[]
{
new object[] { typeof(IOptions<NodeOptions>) },
@@ -781,6 +819,8 @@ public class SiteCompositionRootTests : IDisposable
// --- Hosted services ---
/// <summary>Verifies that the hosted service is registered on a site node.</summary>
/// <param name="expectedType">The hosted service type expected to be registered.</param>
[Theory]
[MemberData(nameof(SiteHostedServices))]
public void Site_HostedServiceRegistered(Type expectedType)
@@ -789,6 +829,7 @@ public class SiteCompositionRootTests : IDisposable
Assert.Contains(hostedServices, s => s.GetType() == expectedType);
}
/// <summary>Gets the hosted service types expected to be registered on a site node.</summary>
public static IEnumerable<object[]> SiteHostedServices => new[]
{
new object[] { typeof(HealthReportSender) },