docs+ui: backfill XML doc comments and finish dashboard layout pass
Adds missing <summary>/<param> XML docs across 99 server, worker, and test files so CommentChecker reports zero issues (TreatWarningsAsErrors needs the analyzer clean). Bundles in WIP dashboard work: NavSection extraction, MainLayout/site.css/js styling alignment, and DashboardOptions/Auth tweaks.
This commit is contained in:
@@ -44,6 +44,7 @@ public sealed class GalaxyFilterInputSafetyTests
|
||||
"Pump'001",
|
||||
];
|
||||
|
||||
/// <summary>Returns adversarial input cases for theory tests.</summary>
|
||||
public static TheoryData<string> AdversarialInputCases()
|
||||
{
|
||||
TheoryData<string> data = [];
|
||||
@@ -60,6 +61,7 @@ public sealed class GalaxyFilterInputSafetyTests
|
||||
/// <c>LIKE</c>-wildcards as literals — a glob equal to the literal value matches,
|
||||
/// and the same glob does not spuriously match an unrelated value.
|
||||
/// </summary>
|
||||
/// <param name="input">An adversarial input containing SQL metacharacters or LIKE wildcards.</param>
|
||||
[Theory]
|
||||
[MemberData(nameof(AdversarialInputCases))]
|
||||
public void GlobMatcher_TreatsSqlMetacharactersAsLiterals(string input)
|
||||
@@ -159,6 +161,7 @@ public sealed class GalaxyFilterInputSafetyTests
|
||||
/// treats an adversarial glob as a literal: it never wildcard-matches the whole
|
||||
/// hierarchy and never throws.
|
||||
/// </summary>
|
||||
/// <param name="glob">An adversarial glob containing SQL metacharacters or LIKE wildcards.</param>
|
||||
[Theory]
|
||||
[MemberData(nameof(AdversarialInputCases))]
|
||||
public void Projector_TagNameGlob_WithAdversarialInput_DoesNotMatchEverything(string glob)
|
||||
@@ -180,6 +183,7 @@ public sealed class GalaxyFilterInputSafetyTests
|
||||
/// literal — an exact-match lookup that finds nothing and surfaces NotFound,
|
||||
/// never matching unrelated objects or throwing an unexpected exception.
|
||||
/// </summary>
|
||||
/// <param name="rootTagName">An adversarial tag name containing SQL metacharacters or LIKE wildcards.</param>
|
||||
[Theory]
|
||||
[MemberData(nameof(AdversarialInputCases))]
|
||||
public void Projector_RootTagName_WithAdversarialInput_ThrowsNotFound(string rootTagName)
|
||||
@@ -198,6 +202,7 @@ public sealed class GalaxyFilterInputSafetyTests
|
||||
/// Verifies an adversarial <c>TemplateChainContains</c> filter is a literal
|
||||
/// substring test — it never matches unrelated template chains and never throws.
|
||||
/// </summary>
|
||||
/// <param name="filter">An adversarial filter containing SQL metacharacters or LIKE wildcards.</param>
|
||||
[Theory]
|
||||
[MemberData(nameof(AdversarialInputCases))]
|
||||
public void Projector_TemplateChainContains_WithAdversarialInput_MatchesNothing(string filter)
|
||||
@@ -216,6 +221,7 @@ public sealed class GalaxyFilterInputSafetyTests
|
||||
/// handles an adversarial <c>TagNameGlob</c> end-to-end: the request succeeds with
|
||||
/// zero matches rather than returning the whole hierarchy or faulting.
|
||||
/// </summary>
|
||||
/// <param name="glob">An adversarial glob containing SQL metacharacters or LIKE wildcards.</param>
|
||||
[Theory]
|
||||
[MemberData(nameof(AdversarialInputCases))]
|
||||
public async Task DiscoverHierarchy_WithAdversarialTagNameGlob_ReturnsZeroMatches(string glob)
|
||||
@@ -235,6 +241,7 @@ public sealed class GalaxyFilterInputSafetyTests
|
||||
/// maps an adversarial <c>RootTagName</c> to NotFound rather than executing it as
|
||||
/// a query fragment or matching unrelated objects.
|
||||
/// </summary>
|
||||
/// <param name="rootTagName">An adversarial tag name containing SQL metacharacters or LIKE wildcards.</param>
|
||||
[Theory]
|
||||
[MemberData(nameof(AdversarialInputCases))]
|
||||
public async Task DiscoverHierarchy_WithAdversarialRootTagName_ReturnsNotFound(string rootTagName)
|
||||
@@ -319,10 +326,13 @@ public sealed class GalaxyFilterInputSafetyTests
|
||||
|
||||
private sealed class StubGalaxyHierarchyCache(GalaxyHierarchyCacheEntry current) : IGalaxyHierarchyCache
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public GalaxyHierarchyCacheEntry Current { get; } = current;
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task RefreshAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task WaitForFirstLoadAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ public sealed class GalaxyHierarchyCacheTests : IDisposable
|
||||
Assert.False(GalaxyHierarchyCacheEntry.Empty.HasData);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the hierarchy index builds paths and lookups without throwing on bad metadata.</summary>
|
||||
[Fact]
|
||||
public void GalaxyHierarchyIndex_BuildsPathsAndTagLookupsWithoutThrowingOnBadMetadata()
|
||||
{
|
||||
@@ -357,19 +358,24 @@ public sealed class GalaxyHierarchyCacheTests : IDisposable
|
||||
{
|
||||
private readonly TaskCompletionSource _release = new(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
|
||||
/// <summary>Releases the blocking task.</summary>
|
||||
public void Release() => _release.TrySetResult();
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<bool> TestConnectionAsync(CancellationToken ct = default) => Task.FromResult(false);
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<DateTime?> GetLastDeployTimeAsync(CancellationToken ct = default)
|
||||
{
|
||||
await _release.Task.WaitAsync(ct).ConfigureAwait(false);
|
||||
throw new InvalidOperationException("Galaxy repository unreachable");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<List<GalaxyHierarchyRow>> GetHierarchyAsync(CancellationToken ct = default)
|
||||
=> throw new InvalidOperationException("GetHierarchyAsync should not be reached");
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<List<GalaxyAttributeRow>> GetAttributesAsync(CancellationToken ct = default)
|
||||
=> throw new InvalidOperationException("GetAttributesAsync should not be reached");
|
||||
}
|
||||
@@ -377,9 +383,11 @@ public sealed class GalaxyHierarchyCacheTests : IDisposable
|
||||
/// <summary>Snapshot store whose <see cref="SaveAsync"/> cancels the token mid-save.</summary>
|
||||
private sealed class CancellingSaveStore(CancellationTokenSource cts) : IGalaxyHierarchySnapshotStore
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public Task<GalaxyHierarchySnapshot?> TryLoadAsync(CancellationToken cancellationToken)
|
||||
=> Task.FromResult<GalaxyHierarchySnapshot?>(null);
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task SaveAsync(GalaxyHierarchySnapshot snapshot, CancellationToken cancellationToken)
|
||||
{
|
||||
cts.Cancel();
|
||||
@@ -391,13 +399,17 @@ public sealed class GalaxyHierarchyCacheTests : IDisposable
|
||||
/// <summary>Minimal <see cref="ILogger{T}"/> that records every emitted log entry.</summary>
|
||||
private sealed class RecordingLogger<T> : ILogger<T>
|
||||
{
|
||||
/// <summary>Gets the list of recorded log entries.</summary>
|
||||
public List<(LogLevel Level, string Message)> Entries { get; } = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
public IDisposable BeginScope<TState>(TState state)
|
||||
where TState : notnull => NullScope.Instance;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsEnabled(LogLevel logLevel) => true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Log<TState>(
|
||||
LogLevel logLevel,
|
||||
EventId eventId,
|
||||
@@ -412,6 +424,7 @@ public sealed class GalaxyHierarchyCacheTests : IDisposable
|
||||
{
|
||||
public static readonly NullScope Instance = new();
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
@@ -427,20 +440,26 @@ public sealed class GalaxyHierarchyCacheTests : IDisposable
|
||||
private readonly List<GalaxyHierarchyRow> _hierarchy = hierarchy ?? [];
|
||||
private readonly List<GalaxyAttributeRow> _attributes = attributes ?? [];
|
||||
|
||||
/// <summary>Gets the count of calls to <see cref="GetHierarchyAsync"/>.</summary>
|
||||
public int GetHierarchyCount { get; private set; }
|
||||
|
||||
/// <summary>Gets the count of calls to <see cref="GetAttributesAsync"/>.</summary>
|
||||
public int GetAttributesCount { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<bool> TestConnectionAsync(CancellationToken ct = default) => Task.FromResult(true);
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<DateTime?> GetLastDeployTimeAsync(CancellationToken ct = default) => Task.FromResult(deployTime);
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<List<GalaxyHierarchyRow>> GetHierarchyAsync(CancellationToken ct = default)
|
||||
{
|
||||
GetHierarchyCount++;
|
||||
return Task.FromResult(_hierarchy);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<List<GalaxyAttributeRow>> GetAttributesAsync(CancellationToken ct = default)
|
||||
{
|
||||
GetAttributesCount++;
|
||||
@@ -448,6 +467,7 @@ public sealed class GalaxyHierarchyCacheTests : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (string path in _tempPaths)
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace ZB.MOM.WW.MxGateway.Tests.Galaxy;
|
||||
/// </summary>
|
||||
public sealed class GalaxyHierarchyProjectorTests
|
||||
{
|
||||
/// <summary>Verifies that paging across a hierarchy returns every object exactly once.</summary>
|
||||
[Fact]
|
||||
public void Project_PagedAcrossEntireHierarchy_ReturnsEveryObjectExactlyOnce()
|
||||
{
|
||||
@@ -43,6 +44,7 @@ public sealed class GalaxyHierarchyProjectorTests
|
||||
Assert.Equal("Object_025", collected[^1]);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that distinct filters on the same entry do not share memoized view list.</summary>
|
||||
[Fact]
|
||||
public void Project_DistinctFiltersOnSameEntry_DoNotShareMemoizedViewList()
|
||||
{
|
||||
@@ -60,6 +62,7 @@ public sealed class GalaxyHierarchyProjectorTests
|
||||
Assert.Equal(10, unfiltered.TotalObjectCount);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the same filter repeated returns identical totals.</summary>
|
||||
[Fact]
|
||||
public void Project_SameFilterRepeated_ReturnsIdenticalTotals()
|
||||
{
|
||||
@@ -85,6 +88,7 @@ public sealed class GalaxyHierarchyProjectorTests
|
||||
Assert.NotEqual(first.Objects[0].TagName, second.Objects[0].TagName);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that distinct cache entries project against their own data.</summary>
|
||||
[Fact]
|
||||
public void Project_DistinctCacheEntries_ProjectAgainstTheirOwnData()
|
||||
{
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace ZB.MOM.WW.MxGateway.Tests.Galaxy;
|
||||
/// </summary>
|
||||
public sealed class GalaxyHierarchyRefreshServiceTests
|
||||
{
|
||||
/// <summary>Verifies that the background service does not fault when the first refresh throws a non-cancellation exception.</summary>
|
||||
[Fact]
|
||||
public async Task ExecuteAsync_WhenFirstRefreshThrowsNonCancellationException_DoesNotFaultBackgroundService()
|
||||
{
|
||||
@@ -62,13 +63,17 @@ public sealed class GalaxyHierarchyRefreshServiceTests
|
||||
private readonly TaskCompletionSource firstRefreshAttempted =
|
||||
new(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
|
||||
/// <summary>Gets the number of refresh calls.</summary>
|
||||
public int RefreshCallCount { get; private set; }
|
||||
|
||||
/// <summary>Completes once <see cref="RefreshAsync"/> has been invoked at least once.</summary>
|
||||
/// <summary>Gets a task that completes once refresh has been invoked at least once.</summary>
|
||||
public Task FirstRefreshAttempted => firstRefreshAttempted.Task;
|
||||
|
||||
/// <summary>Gets the current cache entry.</summary>
|
||||
public GalaxyHierarchyCacheEntry Current => GalaxyHierarchyCacheEntry.Empty;
|
||||
|
||||
/// <summary>Refreshes the cache asynchronously and throws the configured exception.</summary>
|
||||
/// <param name="cancellationToken">Token to observe for cancellation.</param>
|
||||
public Task RefreshAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
RefreshCallCount++;
|
||||
@@ -76,6 +81,8 @@ public sealed class GalaxyHierarchyRefreshServiceTests
|
||||
throw toThrow;
|
||||
}
|
||||
|
||||
/// <summary>Waits for the first load and completes immediately.</summary>
|
||||
/// <param name="cancellationToken">Token to observe for cancellation.</param>
|
||||
public Task WaitForFirstLoadAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ public sealed class GalaxyHierarchySnapshotStoreTests : IDisposable
|
||||
{
|
||||
private readonly List<string> _tempPaths = [];
|
||||
|
||||
/// <summary>Verifies that snapshots are correctly saved to and loaded from disk.</summary>
|
||||
[Fact]
|
||||
public async Task SaveAsync_ThenTryLoadAsync_RoundTripsRows()
|
||||
{
|
||||
@@ -39,6 +40,7 @@ public sealed class GalaxyHierarchySnapshotStoreTests : IDisposable
|
||||
Assert.Null(loaded.Attributes[1].ArrayDimension);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that loading returns null when no snapshot file exists.</summary>
|
||||
[Fact]
|
||||
public async Task TryLoadAsync_WhenNoFileExists_ReturnsNull()
|
||||
{
|
||||
@@ -47,6 +49,7 @@ public sealed class GalaxyHierarchySnapshotStoreTests : IDisposable
|
||||
Assert.Null(await store.TryLoadAsync(CancellationToken.None));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that save writes nothing when persistence is disabled.</summary>
|
||||
[Fact]
|
||||
public async Task SaveAsync_WhenPersistenceDisabled_WritesNothing()
|
||||
{
|
||||
@@ -59,6 +62,7 @@ public sealed class GalaxyHierarchySnapshotStoreTests : IDisposable
|
||||
Assert.Null(await store.TryLoadAsync(CancellationToken.None));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that loading returns null when the file contains invalid JSON.</summary>
|
||||
[Fact]
|
||||
public async Task TryLoadAsync_WhenFileIsCorruptJson_ReturnsNull()
|
||||
{
|
||||
@@ -69,6 +73,7 @@ public sealed class GalaxyHierarchySnapshotStoreTests : IDisposable
|
||||
Assert.Null(await store.TryLoadAsync(CancellationToken.None));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that loading returns null when the schema version is unrecognized.</summary>
|
||||
[Fact]
|
||||
public async Task TryLoadAsync_WhenSchemaVersionUnrecognized_ReturnsNull()
|
||||
{
|
||||
@@ -79,6 +84,7 @@ public sealed class GalaxyHierarchySnapshotStoreTests : IDisposable
|
||||
Assert.Null(await store.TryLoadAsync(CancellationToken.None));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that saving overwrites an earlier snapshot.</summary>
|
||||
[Fact]
|
||||
public async Task SaveAsync_OverwritesAnEarlierSnapshot()
|
||||
{
|
||||
@@ -159,6 +165,7 @@ public sealed class GalaxyHierarchySnapshotStoreTests : IDisposable
|
||||
return path;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (string path in _tempPaths)
|
||||
|
||||
Reference in New Issue
Block a user