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
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:
@@ -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()
|
||||
{
|
||||
|
||||
+53
-1
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user