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
@@ -15,6 +15,9 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Tests.Browse;
/// </summary>
public sealed class DataTypeMapTests
{
/// <summary>Verifies that Map maps known codes to expected driver data types.</summary>
/// <param name="mxDataType">The Galaxy mx_data_type integer code.</param>
/// <param name="expected">The expected driver data type.</param>
[Theory]
[InlineData(0, DriverDataType.Boolean)]
[InlineData(1, DriverDataType.Int32)]
@@ -28,6 +31,7 @@ public sealed class DataTypeMapTests
DataTypeMap.Map(mxDataType).ShouldBe(expected);
}
/// <summary>Verifies that Int64 code does not fall through to String default.</summary>
[Fact]
public void Map_Int64Code_DoesNotFallThroughToStringDefault()
{
@@ -36,6 +40,8 @@ public sealed class DataTypeMapTests
DataTypeMap.Map(6).ShouldNotBe(DriverDataType.String);
}
/// <summary>Verifies that unknown code falls back to String.</summary>
/// <param name="mxDataType">An unrecognised Galaxy mx_data_type code.</param>
[Theory]
[InlineData(7)]
[InlineData(99)]
@@ -23,20 +23,46 @@ public sealed class DeployWatcherTests
private sealed class FakeDeployWatchSource : IGalaxyDeployWatchSource
{
private readonly Func<int, Channel<DeployEvent>> _channelFactory;
/// <summary>
/// Gets the list of last-seen deployment times from each watch iteration.
/// </summary>
public List<DateTimeOffset?> LastSeenTimes { get; } = [];
/// <summary>
/// Gets the number of times WatchAsync has been called.
/// </summary>
public int CallCount { get; private set; }
/// <summary>
/// Gets or sets a function that can throw an exception on specific iterations.
/// </summary>
public Func<int, Exception?>? ThrowOnIteration { get; init; }
/// <summary>
/// Initializes a new instance of the <see cref="FakeDeployWatchSource"/> class with a single channel.
/// </summary>
/// <param name="channel">The deploy event channel to use for all iterations.</param>
public FakeDeployWatchSource(Channel<DeployEvent> channel)
{
_channelFactory = _ => channel;
}
/// <summary>
/// Initializes a new instance of the <see cref="FakeDeployWatchSource"/> class with a channel factory.
/// </summary>
/// <param name="channelFactory">A factory function that creates channels for each iteration.</param>
public FakeDeployWatchSource(Func<int, Channel<DeployEvent>> channelFactory)
{
_channelFactory = channelFactory;
}
/// <summary>
/// Watches for deploy events asynchronously.
/// </summary>
/// <param name="lastSeenDeployTime">The last deployment time seen.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>An async enumerable of deploy events.</returns>
public async IAsyncEnumerable<DeployEvent> WatchAsync(
DateTimeOffset? lastSeenDeployTime,
[EnumeratorCancellation] CancellationToken cancellationToken)
@@ -93,6 +119,7 @@ public sealed class DeployWatcherTests
throw new TimeoutException("Condition was not met within timeout.");
}
/// <summary>Verifies that bootstrap deploy events are suppressed.</summary>
[Fact]
public async Task BootstrapEventIsSuppressed()
{
@@ -115,6 +142,7 @@ public sealed class DeployWatcherTests
await watcher.StopAsync();
}
/// <summary>Verifies that a deployment time change fires a rediscovery event.</summary>
[Fact]
public async Task DeployTimeChangeFiresRediscover()
{
@@ -142,6 +170,7 @@ public sealed class DeployWatcherTests
await watcher.StopAsync();
}
/// <summary>Verifies that the same deployment time does not fire a rediscovery event.</summary>
[Fact]
public async Task SameDeployTimeDoesNotFire()
{
@@ -165,6 +194,7 @@ public sealed class DeployWatcherTests
await watcher.StopAsync();
}
/// <summary>Verifies that a deployment time presence flip fires a rediscovery event.</summary>
[Fact]
public async Task TimeOfLastDeployPresentFlipFiresRediscover()
{
@@ -191,6 +221,7 @@ public sealed class DeployWatcherTests
await watcher.StopAsync();
}
/// <summary>Verifies that stop cancels the watcher loop cleanly.</summary>
[Fact]
public async Task StopCancelsLoopCleanly()
{
@@ -211,6 +242,7 @@ public sealed class DeployWatcherTests
await stopTask; // observe (no) exception
}
/// <summary>Verifies that disposing stops a running watcher.</summary>
[Fact]
public async Task DisposeStopsRunningWatcher()
{
@@ -229,6 +261,7 @@ public sealed class DeployWatcherTests
await disposeTask;
}
/// <summary>Verifies that a source exception triggers retry with backoff.</summary>
[Fact]
public async Task SourceExceptionTriggersRetryWithBackoff()
{
@@ -16,6 +16,9 @@ public sealed class GalaxyDiscovererTests
{
private sealed class FakeHierarchySource(IReadOnlyList<GalaxyObject> objects) : IGalaxyHierarchySource
{
/// <summary>Gets the hierarchy asynchronously from the fake source.</summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>A task that returns the pre-built Galaxy object list.</returns>
public Task<IReadOnlyList<GalaxyObject>> GetHierarchyAsync(CancellationToken cancellationToken)
=> Task.FromResult(objects);
}
@@ -25,15 +28,23 @@ public sealed class GalaxyDiscovererTests
private sealed class FakeBuilder : IAddressSpaceBuilder
{
/// <summary>Gets the list of folder creation calls recorded by this builder.</summary>
public List<FolderCall> Folders { get; } = [];
/// <summary>Gets the list of variable creation calls recorded by this builder.</summary>
public List<VariableCall> Variables { get; } = [];
/// <summary>Gets the dictionary of alarm declarations recorded by this builder.</summary>
public Dictionary<string, AlarmConditionInfo> AlarmDeclarations { get; } = [];
private readonly string? _currentFolder;
/// <summary>Initializes a new instance of the FakeBuilder class at the root level.</summary>
public FakeBuilder() : this(null) { }
private FakeBuilder(string? folder) { _currentFolder = folder; }
/// <summary>Adds a folder call to the recorded list.</summary>
/// <param name="browseName">The browse name for the folder.</param>
/// <param name="displayName">The display name for the folder.</param>
/// <returns>An IAddressSpaceBuilder scoped to the new folder.</returns>
public IAddressSpaceBuilder Folder(string browseName, string displayName)
{
Folders.Add(new FolderCall(browseName, displayName));
@@ -41,6 +52,11 @@ public sealed class GalaxyDiscovererTests
return new ChildBuilder(this, browseName);
}
/// <summary>Adds a variable call to the recorded list.</summary>
/// <param name="browseName">The browse name for the variable.</param>
/// <param name="displayName">The display name for the variable.</param>
/// <param name="attributeInfo">The attribute metadata for the variable.</param>
/// <returns>An IVariableHandle for further configuration.</returns>
public IVariableHandle Variable(string browseName, string displayName, DriverAttributeInfo attributeInfo)
{
var folder = _currentFolder ?? "<root>";
@@ -48,30 +64,51 @@ public sealed class GalaxyDiscovererTests
return new FakeVariableHandle(this, attributeInfo.FullName);
}
/// <summary>Adds a property call to the builder (not recorded in this fake).</summary>
/// <param name="browseName">The browse name for the property.</param>
/// <param name="dataType">The driver data type of the property.</param>
/// <param name="value">The property value.</param>
public void AddProperty(string browseName, DriverDataType dataType, object? value) { }
// Child folder routes Variable calls back to the parent's lists with its own scope.
/// <summary>Child folder routes Variable calls back to the parent's lists with its own scope.</summary>
private sealed class ChildBuilder(FakeBuilder parent, string folderBrowseName) : IAddressSpaceBuilder
{
/// <summary>Adds a child folder call to the parent builder's recorded list.</summary>
/// <param name="browseName">The browse name for the folder.</param>
/// <param name="displayName">The display name for the folder.</param>
/// <returns>An IAddressSpaceBuilder scoped to the new child folder.</returns>
public IAddressSpaceBuilder Folder(string browseName, string displayName)
{
parent.Folders.Add(new FolderCall(browseName, displayName));
return new ChildBuilder(parent, browseName);
}
/// <summary>Adds a variable call to the parent builder's recorded list, scoped to this folder.</summary>
/// <param name="browseName">The browse name for the variable.</param>
/// <param name="displayName">The display name for the variable.</param>
/// <param name="attributeInfo">The attribute metadata for the variable.</param>
/// <returns>An IVariableHandle for further configuration.</returns>
public IVariableHandle Variable(string browseName, string displayName, DriverAttributeInfo attributeInfo)
{
parent.Variables.Add(new VariableCall(folderBrowseName, browseName, attributeInfo));
return new FakeVariableHandle(parent, attributeInfo.FullName);
}
/// <summary>Adds a property call to the builder (not recorded in this fake).</summary>
/// <param name="browseName">The browse name for the property.</param>
/// <param name="dataType">The driver data type of the property.</param>
/// <param name="value">The property value.</param>
public void AddProperty(string browseName, DriverDataType dataType, object? value) { }
}
private sealed class FakeVariableHandle(FakeBuilder owner, string fullRef) : IVariableHandle
{
/// <summary>Gets the full reference for this variable.</summary>
public string FullReference { get; } = fullRef;
/// <summary>Marks this variable as an alarm condition and records it.</summary>
/// <param name="info">The alarm condition metadata.</param>
/// <returns>An IAlarmConditionSink for further alarm configuration.</returns>
public IAlarmConditionSink MarkAsAlarmCondition(AlarmConditionInfo info)
{
owner.AlarmDeclarations[FullReference] = info;
@@ -81,6 +118,8 @@ public sealed class GalaxyDiscovererTests
private sealed class NoopSink : IAlarmConditionSink
{
/// <summary>Records an alarm transition event (no-op in this fake).</summary>
/// <param name="args">The alarm event arguments.</param>
public void OnTransition(AlarmEventArgs args) { }
}
}
@@ -116,6 +155,7 @@ public sealed class GalaxyDiscovererTests
return o;
}
/// <summary>Verifies that discovery creates one folder per object and one variable per attribute.</summary>
[Fact]
public async Task DiscoverAsync_BuildsOneFolderPerObject_AndOneVariablePerAttribute()
{
@@ -137,6 +177,7 @@ public sealed class GalaxyDiscovererTests
builder.Variables.ShouldContain(v => v.FolderBrowseName == "Pump" && v.AttributeName == "Running");
}
/// <summary>Verifies that full reference defaults to tag.attribute format when not explicitly supplied.</summary>
[Fact]
public async Task DiscoverAsync_FullReference_DefaultsToTagDotAttribute()
{
@@ -151,6 +192,7 @@ public sealed class GalaxyDiscovererTests
builder.Variables[0].Info.FullName.ShouldBe("Tank1_Level.PV");
}
/// <summary>Verifies that full reference uses gateway-supplied value when provided.</summary>
[Fact]
public async Task DiscoverAsync_FullReference_PrefersGwSuppliedFullTagReference()
{
@@ -165,6 +207,7 @@ public sealed class GalaxyDiscovererTests
builder.Variables[0].Info.FullName.ShouldBe("explicit.full.ref");
}
/// <summary>Verifies that browse name falls back to tag name when contained name is empty.</summary>
[Fact]
public async Task DiscoverAsync_BrowseName_FallsBackToTagName_WhenContainedEmpty()
{
@@ -179,6 +222,7 @@ public sealed class GalaxyDiscovererTests
builder.Folders[0].BrowseName.ShouldBe("Tank1_Level");
}
/// <summary>Verifies that attribute metadata fields are all propagated to the discovered variable.</summary>
[Fact]
public async Task DiscoverAsync_AttributeMetadata_PropagatesEveryField()
{
@@ -203,6 +247,7 @@ public sealed class GalaxyDiscovererTests
info.IsAlarm.ShouldBeFalse();
}
/// <summary>Verifies that alarm attributes populate all five sub-attribute references.</summary>
[Fact]
public async Task DiscoverAsync_AlarmAttribute_PopulatesAllFiveSubAttributeRefs()
{
@@ -224,6 +269,7 @@ public sealed class GalaxyDiscovererTests
info.AckMsgWriteRef.ShouldBe("Tank1_Level.HiHi.AckMsg");
}
/// <summary>Verifies that non-alarm attributes are not marked as alarm conditions.</summary>
[Fact]
public async Task DiscoverAsync_NonAlarmAttribute_DoesNotMarkCondition()
{
@@ -240,6 +286,7 @@ public sealed class GalaxyDiscovererTests
builder.AlarmDeclarations.ShouldNotContainKey("T.PV");
}
/// <summary>Verifies that objects with empty identity are skipped during discovery.</summary>
[Fact]
public async Task DiscoverAsync_SkipsObjectsWithEmptyIdentity()
{
@@ -256,6 +303,7 @@ public sealed class GalaxyDiscovererTests
builder.Folders[0].BrowseName.ShouldBe("Real");
}
/// <summary>Verifies that attributes with empty names are skipped during discovery.</summary>
[Fact]
public async Task DiscoverAsync_SkipsAttributesWithEmptyName()
{
@@ -271,6 +319,7 @@ public sealed class GalaxyDiscovererTests
builder.Variables[0].AttributeName.ShouldBe("PV");
}
/// <summary>Verifies that driver discovery routes through the injected hierarchy source.</summary>
[Fact]
public async Task DriverDiscoverAsync_RoutesThroughInjectedSource()
{
@@ -287,6 +336,9 @@ public sealed class GalaxyDiscovererTests
/// <summary>Helper that exercises the internal ctor (test seam) without exposing it publicly.</summary>
private sealed class GalaxyDriverHelper
{
/// <summary>Creates a GalaxyDriver with a fake hierarchy source for testing.</summary>
/// <param name="source">The fake hierarchy source to inject.</param>
/// <returns>A GalaxyDriver configured with the fake source.</returns>
public GalaxyDriver CreateWithFakeSource(IGalaxyHierarchySource source)
=> new GalaxyDriver(
"galaxy-test",