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:
@@ -1,20 +1,20 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.LoadHarness;
|
||||
|
||||
/// <summary>
|
||||
/// Scale and duration knobs for a load-harness run. Defaults are the Phase-8 WP-4
|
||||
/// Scale and duration knobs for a load-harness run. Defaults are the
|
||||
/// target scale (10 sites x 500 instances x 75 tags = 375,000 subscriptions).
|
||||
/// Every value is overridable from the command line so the same binary serves both
|
||||
/// the full-scale protocol run and the scaled-down CI smoke.
|
||||
/// </summary>
|
||||
public sealed record HarnessConfig
|
||||
{
|
||||
/// <summary>Number of simulated sites (WP-4 acceptance criterion <c>[2.5-1]</c>).</summary>
|
||||
/// <summary>Number of simulated sites (acceptance criterion <c>[2.5-1]</c>).</summary>
|
||||
public int Sites { get; init; } = 10;
|
||||
|
||||
/// <summary>Instance Actors per site (WP-4 <c>[2.5-2]</c>).</summary>
|
||||
/// <summary>Instance Actors per site (acceptance criterion <c>[2.5-2]</c>).</summary>
|
||||
public int InstancesPerSite { get; init; } = 500;
|
||||
|
||||
/// <summary>Data-sourced attributes ("live tags") per instance (WP-4 <c>[2.5-3]</c>).</summary>
|
||||
/// <summary>Data-sourced attributes ("live tags") per instance (acceptance criterion <c>[2.5-3]</c>).</summary>
|
||||
public int TagsPerInstance { get; init; } = 75;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -27,8 +27,8 @@ namespace ZB.MOM.WW.ScadaBridge.LoadHarness;
|
||||
/// <param name="ResourceSamples">
|
||||
/// Every raw resource sample. Retained because the summary alone cannot distinguish a
|
||||
/// slow leak from a heap that simply sawtooths — especially when the run records zero
|
||||
/// gen-2 collections, where a positive least-squares slope may be nothing more than
|
||||
/// gen-2 garbage that was never collected.
|
||||
/// gen 2 collections, where a positive least-squares slope may be nothing more than
|
||||
/// gen 2 garbage that was never collected.
|
||||
/// </param>
|
||||
/// <param name="HealthReportLatency">Health report collect+ingest latency.</param>
|
||||
/// <param name="HealthReportsDelivered">Health reports ingested by the central aggregator.</param>
|
||||
@@ -112,7 +112,7 @@ public sealed record EnvironmentInfo(
|
||||
/// <summary>
|
||||
/// Orchestrates a full run: build sites, ramp instances, attach subscribers, drive
|
||||
/// tag updates for the sustained window while sampling resources and probing
|
||||
/// observability, then run the two register-row-50 scenarios on a dedicated site.
|
||||
/// observability, then run the two deferred-register scenarios on a dedicated site.
|
||||
/// </summary>
|
||||
public static class HarnessRun
|
||||
{
|
||||
@@ -251,7 +251,7 @@ public static class HarnessRun
|
||||
var probeReceived = sites.Sum(s => s.Probes.Sum(p => p.ReceivedEvents)) - receivedAtWindowStart;
|
||||
var probeDropped = sites.Sum(s => s.Probes.Sum(p => p.DroppedEvents)) - droppedAtWindowStart;
|
||||
|
||||
// Wire-path window deltas, captured BEFORE the row-50 scenarios below so
|
||||
// Wire-path window deltas, captured BEFORE the deferred-register scenarios below so
|
||||
// their publishing cannot contaminate the wire figures.
|
||||
WireStreamResult? wireResult = null;
|
||||
if (batchAggregator is not null)
|
||||
|
||||
@@ -61,7 +61,7 @@ public sealed class BatchSizeAggregator : IDisposable
|
||||
return copy;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Disposes the underlying meter listener.</summary>
|
||||
public void Dispose() => _listener.Dispose();
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace ZB.MOM.WW.ScadaBridge.LoadHarness.Metrics;
|
||||
/// <param name="ManagedHeapMb"><see cref="GC.GetTotalMemory(bool)"/> without forcing a collection.</param>
|
||||
/// <param name="CpuPercent">Mean CPU utilization since the previous sample, as a percentage of ONE core.</param>
|
||||
/// <param name="ThreadCount">OS threads in the process.</param>
|
||||
/// <param name="Gen2Collections">Cumulative gen-2 collections.</param>
|
||||
/// <param name="Gen2Collections">Cumulative generation 2 collections.</param>
|
||||
public sealed record ResourceSample(
|
||||
double ElapsedSeconds,
|
||||
double WorkingSetMb,
|
||||
@@ -150,7 +150,8 @@ public sealed class ResourceSampler : IAsyncDisposable
|
||||
|
||||
private int _disposed;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Stops the sampling loop and releases the sampler's resources.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
if (Interlocked.Exchange(ref _disposed, 1) != 0)
|
||||
@@ -184,7 +185,7 @@ public sealed class ResourceSampler : IAsyncDisposable
|
||||
/// <param name="MeanCpuPercentOfOneCore">Mean CPU as a percentage of one core (1400% = 14 cores saturated).</param>
|
||||
/// <param name="PeakCpuPercentOfOneCore">Peak single-sample CPU as a percentage of one core.</param>
|
||||
/// <param name="MeanThreadCount">Mean OS thread count.</param>
|
||||
/// <param name="Gen2Collections">Gen-2 collections during the window.</param>
|
||||
/// <param name="Gen2Collections">Generation 2 collections during the window.</param>
|
||||
public sealed record ResourceWindowSummary(
|
||||
int SampleCount,
|
||||
double DurationSeconds,
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace ZB.MOM.WW.ScadaBridge.LoadHarness.Probes;
|
||||
/// <para>
|
||||
/// This is the hop <see cref="StreamSubscriberProbe"/> deliberately substitutes with a
|
||||
/// controllable in-process reader (which the slow-subscriber scenario needs), and
|
||||
/// therefore the hop the original WP-4 runs never exercised: the
|
||||
/// therefore the hop the original runs never exercised: the
|
||||
/// <c>SiteStreamEventBatcher</c> pump (R2), protobuf serialization,
|
||||
/// <c>IServerStreamWriter.WriteAsync</c>, and HTTP/2 flow control. The server is built
|
||||
/// through its production DI constructor with default <see cref="CommunicationOptions"/>,
|
||||
@@ -84,7 +84,8 @@ public sealed class SiteWireStreamHost : IAsyncDisposable
|
||||
return new SiteWireStreamHost(app, server, address);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Cancels active streams and stops and disposes the underlying listener.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
// Mirrors the production shutdown ordering: cancel active streams first so
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using System.Text.Json;
|
||||
using ZB.MOM.WW.ScadaBridge.LoadHarness;
|
||||
|
||||
// Target-scale load harness (Phase-8 WP-4 / deferred-work register #25 + row 50).
|
||||
// Target-scale load harness.
|
||||
//
|
||||
// Full-scale protocol run (the WP-4 numbers):
|
||||
// Full-scale protocol run (the target-scale numbers):
|
||||
// dotnet run -c Release --project tests/ZB.MOM.WW.ScadaBridge.LoadHarness -- \
|
||||
// --sustain-minutes 20 --results loadharness-results.json
|
||||
//
|
||||
|
||||
@@ -7,7 +7,7 @@ using ZB.MOM.WW.ScadaBridge.LoadHarness.Metrics;
|
||||
namespace ZB.MOM.WW.ScadaBridge.LoadHarness.Scenarios;
|
||||
|
||||
/// <summary>
|
||||
/// The two "does observability still work at scale?" probes WP-4's test protocol
|
||||
/// The two "does observability still work at scale?" probes the target-scale test protocol
|
||||
/// names — health report delivery timing and debug view latency — run continuously
|
||||
/// alongside the sustained load rather than after it, so both are measured against a
|
||||
/// site that is actually busy.
|
||||
@@ -137,7 +137,8 @@ public sealed class ObservabilityProbes : IAsyncDisposable
|
||||
|
||||
private int _disposed;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Stops the probes and releases their resources.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
// Idempotent: the orchestrator stops the probes early (so the register row 50
|
||||
|
||||
@@ -49,7 +49,7 @@ public sealed record DrainProgressSample(double ElapsedSeconds, long Delivered,
|
||||
/// Phase 1 buffers <paramref name="messageCount"/> messages with
|
||||
/// <c>attemptImmediateDelivery: false</c>, spread across many origin instance names
|
||||
/// and issued from many concurrent tasks — the "concurrent buffering from multiple
|
||||
/// instances" WP-4 asks about (<c>[xc-7]</c>). Phase 2 registers a delivery handler
|
||||
/// instances" case the load test targets. Phase 2 registers a delivery handler
|
||||
/// that always succeeds and drives sweeps to completion, timing the drain.
|
||||
/// </para>
|
||||
/// <para>
|
||||
|
||||
@@ -44,10 +44,11 @@ public sealed class SimulatedDataConnection : IDataConnection, IBatchSubscribabl
|
||||
/// <summary>Key under which the connection name travels in the connection details.</summary>
|
||||
public const string ConnectionNameKey = "connectionName";
|
||||
|
||||
// Gets the current health of the simulated connection.
|
||||
/// <inheritdoc />
|
||||
public ConnectionHealth Status { get; private set; } = ConnectionHealth.Disconnected;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Raised when the simulated connection is disconnected.</summary>
|
||||
public event Action? Disconnected;
|
||||
|
||||
/// <summary>
|
||||
@@ -60,6 +61,7 @@ public sealed class SimulatedDataConnection : IDataConnection, IBatchSubscribabl
|
||||
/// <summary>Number of tag paths this connection has accepted subscriptions for.</summary>
|
||||
public int SubscribedTagCount => _subscriptionCounter;
|
||||
|
||||
// Marks the connection as connected and records the connection name from the details, if present.
|
||||
/// <inheritdoc />
|
||||
public Task ConnectAsync(IDictionary<string, string> connectionDetails, CancellationToken cancellationToken = default)
|
||||
{
|
||||
@@ -70,6 +72,7 @@ public sealed class SimulatedDataConnection : IDataConnection, IBatchSubscribabl
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
// Marks the connection as disconnected and raises the Disconnected event.
|
||||
/// <inheritdoc />
|
||||
public Task DisconnectAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
@@ -78,6 +81,7 @@ public sealed class SimulatedDataConnection : IDataConnection, IBatchSubscribabl
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
// Captures the callback and returns a new subscription id.
|
||||
/// <inheritdoc />
|
||||
public Task<string> SubscribeAsync(string tagPath, SubscriptionCallback callback, CancellationToken cancellationToken = default)
|
||||
{
|
||||
@@ -85,6 +89,7 @@ public sealed class SimulatedDataConnection : IDataConnection, IBatchSubscribabl
|
||||
return Task.FromResult($"sub-{Interlocked.Increment(ref _subscriptionCounter)}");
|
||||
}
|
||||
|
||||
// Captures the callback and accepts every tag path in the batch.
|
||||
/// <inheritdoc />
|
||||
public Task<IReadOnlyList<TagSubscribeResult>> SubscribeBatchAsync(
|
||||
IReadOnlyList<string> tagPaths,
|
||||
@@ -102,18 +107,22 @@ public sealed class SimulatedDataConnection : IDataConnection, IBatchSubscribabl
|
||||
return Task.FromResult<IReadOnlyList<TagSubscribeResult>>(results);
|
||||
}
|
||||
|
||||
// Does nothing; the simulated connection keeps no per-subscription state.
|
||||
/// <inheritdoc />
|
||||
public Task UnsubscribeAsync(string subscriptionId, CancellationToken cancellationToken = default)
|
||||
=> Task.CompletedTask;
|
||||
|
||||
// Does nothing; the simulated connection keeps no per-subscription state.
|
||||
/// <inheritdoc />
|
||||
public Task UnsubscribeBatchAsync(IReadOnlyList<string> subscriptionIds, CancellationToken cancellationToken = default)
|
||||
=> Task.CompletedTask;
|
||||
|
||||
// Returns a good-quality zero value for any tag.
|
||||
/// <inheritdoc />
|
||||
public Task<ReadResult> ReadAsync(string tagPath, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult(new ReadResult(true, new TagValue(0d, QualityCode.Good, DateTimeOffset.UtcNow), null));
|
||||
|
||||
// Returns a good-quality zero value for every requested tag.
|
||||
/// <inheritdoc />
|
||||
public Task<IReadOnlyDictionary<string, ReadResult>> ReadBatchAsync(
|
||||
IEnumerable<string> tagPaths, CancellationToken cancellationToken = default)
|
||||
@@ -126,10 +135,12 @@ public sealed class SimulatedDataConnection : IDataConnection, IBatchSubscribabl
|
||||
return Task.FromResult<IReadOnlyDictionary<string, ReadResult>>(results);
|
||||
}
|
||||
|
||||
// Accepts the write without storing it.
|
||||
/// <inheritdoc />
|
||||
public Task<WriteResult> WriteAsync(string tagPath, object? value, CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult(new WriteResult(true, null));
|
||||
|
||||
// Accepts every write in the batch without storing it.
|
||||
/// <inheritdoc />
|
||||
public Task<IReadOnlyDictionary<string, WriteResult>> WriteBatchAsync(
|
||||
IDictionary<string, object?> values, CancellationToken cancellationToken = default)
|
||||
@@ -141,6 +152,7 @@ public sealed class SimulatedDataConnection : IDataConnection, IBatchSubscribabl
|
||||
return Task.FromResult<IReadOnlyDictionary<string, WriteResult>>(results);
|
||||
}
|
||||
|
||||
// Accepts the batch and reports that the awaited response matched immediately.
|
||||
/// <inheritdoc />
|
||||
public Task<bool> WriteBatchAndWaitAsync(
|
||||
IDictionary<string, object?> values, string flagPath, object? flagValue,
|
||||
@@ -148,6 +160,7 @@ public sealed class SimulatedDataConnection : IDataConnection, IBatchSubscribabl
|
||||
CancellationToken cancellationToken = default)
|
||||
=> Task.FromResult(true);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Releases the connection; the simulated connection holds no resources.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
public ValueTask DisposeAsync() => ValueTask.CompletedTask;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace ZB.MOM.WW.ScadaBridge.LoadHarness;
|
||||
/// The sites are separate, non-clustered ActorSystems rather than 10 real two-node
|
||||
/// Akka clusters. Cluster membership, singleton placement and failover timing are
|
||||
/// already measured on a real two-node rig by
|
||||
/// <c>PerformanceTests/Failover/FailoverTimingTests.cs</c>; what WP-4 asks about is
|
||||
/// <c>PerformanceTests/Failover/FailoverTimingTests.cs</c>; what matters here is
|
||||
/// the load-bearing hierarchy under each singleton, which is what this builds.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
@@ -50,7 +50,7 @@ public sealed class SiteRuntimeFixture : IAsyncDisposable
|
||||
private SiteStreamGrpcClient? _wireClient;
|
||||
private CancellationTokenSource? _wireCts;
|
||||
|
||||
/// <summary>Site identifier, e.g. <c>site-01</c>.</summary>
|
||||
/// <summary>Site identifier, for example a zero-padded numbered name for the first site.</summary>
|
||||
public string SiteId { get; }
|
||||
|
||||
/// <summary>This site's actor system.</summary>
|
||||
@@ -393,7 +393,8 @@ public sealed class SiteRuntimeFixture : IAsyncDisposable
|
||||
/// <summary>Total tag paths registered across this site's connections.</summary>
|
||||
public int TotalTagPaths => TagPathsByConnection.Sum(list => list.Count);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Stops the wire path, the actor system and the data directory in production teardown order.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
// Wire path first: cancel the client streams, wait for their loops to exit,
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace ZB.MOM.WW.ScadaBridge.LoadHarness;
|
||||
/// <c>DataConnectionActor</c> has exactly one adapter feeding it, and every update
|
||||
/// for that connection funnels through that actor's single mailbox. Sharding the
|
||||
/// emitters differently would hide the per-connection-actor serialization point,
|
||||
/// which is one of the things WP-4 needs to characterize.
|
||||
/// which is one of the things the load test needs to characterize.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The emitter walks the connection's tag list in slices sized so that one full pass
|
||||
@@ -154,7 +154,8 @@ public sealed class TagUpdateDriver : IAsyncDisposable
|
||||
|
||||
private int _disposed;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Cancels the emitter tasks, waits for them to finish and releases the cancellation source.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
if (Interlocked.Exchange(ref _disposed, 1) != 0)
|
||||
|
||||
Reference in New Issue
Block a user