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:
@@ -7,6 +7,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
|
||||
|
||||
public class AlarmsCommandTests
|
||||
{
|
||||
/// <summary>Verifies that Execute subscribes to alarms.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_SubscribesToAlarms()
|
||||
{
|
||||
@@ -31,6 +32,7 @@ public class AlarmsCommandTests
|
||||
fakeService.SubscribeAlarmsCalls[0].SourceNodeId.ShouldBeNull();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that Execute with node passes source node ID.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_WithNode_PassesSourceNodeId()
|
||||
{
|
||||
@@ -55,6 +57,7 @@ public class AlarmsCommandTests
|
||||
fakeService.SubscribeAlarmsCalls[0].SourceNodeId!.Identifier.ShouldBe("AlarmSource");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that Execute with refresh requests condition refresh.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_WithRefresh_RequestsConditionRefresh()
|
||||
{
|
||||
@@ -79,6 +82,7 @@ public class AlarmsCommandTests
|
||||
output.ShouldContain("Condition refresh requested.");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that refresh failure prints error.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_RefreshFailure_PrintsError()
|
||||
{
|
||||
@@ -105,6 +109,7 @@ public class AlarmsCommandTests
|
||||
output.ShouldContain("Condition refresh not supported:");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that Execute unsubscribes on cancellation.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_UnsubscribesOnCancellation()
|
||||
{
|
||||
@@ -126,6 +131,7 @@ public class AlarmsCommandTests
|
||||
fakeService.UnsubscribeAlarmsCalled.ShouldBeTrue();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that Execute disconnects in finally block.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_DisconnectsInFinally()
|
||||
{
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
|
||||
|
||||
public class BrowseCommandTests
|
||||
{
|
||||
/// <summary>Verifies that Execute prints browse results correctly.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_PrintsBrowseResults()
|
||||
{
|
||||
@@ -35,6 +36,7 @@ public class BrowseCommandTests
|
||||
output.ShouldContain("[Method] Method1 (NodeId: ns=2;s=Meth1)");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that Execute browses from the specified node ID.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_BrowsesFromSpecifiedNode()
|
||||
{
|
||||
@@ -57,6 +59,7 @@ public class BrowseCommandTests
|
||||
fakeService.BrowseNodeIds[0]!.Identifier.ShouldBe("StartNode");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that Execute browses from null node when not specified.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_DefaultBrowsesFromNull()
|
||||
{
|
||||
@@ -77,6 +80,7 @@ public class BrowseCommandTests
|
||||
fakeService.BrowseNodeIds[0].ShouldBeNull();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that Execute browses only a single level when not recursive.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_NonRecursive_BrowsesSingleLevel()
|
||||
{
|
||||
@@ -101,6 +105,7 @@ public class BrowseCommandTests
|
||||
fakeService.BrowseNodeIds.Count.ShouldBe(1);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that Execute browses child nodes when recursive flag is set.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_Recursive_BrowsesChildren()
|
||||
{
|
||||
@@ -123,6 +128,7 @@ public class BrowseCommandTests
|
||||
fakeService.BrowseNodeIds.Count.ShouldBeGreaterThan(1);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that Execute disconnects and disposes in the finally block.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_DisconnectsInFinally()
|
||||
{
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
|
||||
|
||||
public class CommandBaseTests
|
||||
{
|
||||
/// <summary>Verifies that common options map to connection settings correctly.</summary>
|
||||
[Fact]
|
||||
public async Task CommonOptions_MapToConnectionSettings_Correctly()
|
||||
{
|
||||
@@ -37,6 +38,7 @@ public class CommandBaseTests
|
||||
settings.AutoAcceptCertificates.ShouldBeTrue();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that encrypt option maps to SignAndEncrypt.</summary>
|
||||
[Fact]
|
||||
public async Task SecurityOption_Encrypt_MapsToSignAndEncrypt()
|
||||
{
|
||||
@@ -54,6 +56,7 @@ public class CommandBaseTests
|
||||
fakeService.LastConnectionSettings!.SecurityMode.ShouldBe(SecurityMode.SignAndEncrypt);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that none option maps to None.</summary>
|
||||
[Fact]
|
||||
public async Task SecurityOption_None_MapsToNone()
|
||||
{
|
||||
@@ -71,6 +74,7 @@ public class CommandBaseTests
|
||||
fakeService.LastConnectionSettings!.SecurityMode.ShouldBe(SecurityMode.None);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that no failover URLs results in null FailoverUrls.</summary>
|
||||
[Fact]
|
||||
public async Task NoFailoverUrls_FailoverUrlsIsNull()
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
|
||||
/// </summary>
|
||||
public class CommandRangeValidationTests
|
||||
{
|
||||
/// <summary>Verifies that BrowseCommand rejects negative depth values with a command exception.</summary>
|
||||
[Fact]
|
||||
public async Task BrowseCommand_NegativeDepth_ThrowsCommandException()
|
||||
{
|
||||
@@ -28,6 +29,7 @@ public class CommandRangeValidationTests
|
||||
ex.Message.ShouldContain("--depth");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that BrowseCommand rejects zero depth values with a command exception.</summary>
|
||||
[Fact]
|
||||
public async Task BrowseCommand_ZeroDepth_ThrowsCommandException()
|
||||
{
|
||||
@@ -44,6 +46,7 @@ public class CommandRangeValidationTests
|
||||
ex.Message.ShouldContain("--depth");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that SubscribeCommand rejects zero interval values with a command exception.</summary>
|
||||
[Fact]
|
||||
public async Task SubscribeCommand_ZeroInterval_ThrowsCommandException()
|
||||
{
|
||||
@@ -61,6 +64,7 @@ public class CommandRangeValidationTests
|
||||
ex.Message.ShouldContain("--interval");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that SubscribeCommand rejects negative interval values with a command exception.</summary>
|
||||
[Fact]
|
||||
public async Task SubscribeCommand_NegativeInterval_ThrowsCommandException()
|
||||
{
|
||||
@@ -77,6 +81,7 @@ public class CommandRangeValidationTests
|
||||
await Should.ThrowAsync<CommandException>(async () => await command.ExecuteAsync(console));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that SubscribeCommand in recursive mode rejects zero max depth with a command exception.</summary>
|
||||
[Fact]
|
||||
public async Task SubscribeCommand_RecursiveZeroMaxDepth_ThrowsCommandException()
|
||||
{
|
||||
@@ -96,6 +101,7 @@ public class CommandRangeValidationTests
|
||||
ex.Message.ShouldContain("--max-depth");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that SubscribeCommand rejects negative duration values with a command exception.</summary>
|
||||
[Fact]
|
||||
public async Task SubscribeCommand_NegativeDuration_ThrowsCommandException()
|
||||
{
|
||||
@@ -112,6 +118,7 @@ public class CommandRangeValidationTests
|
||||
await Should.ThrowAsync<CommandException>(async () => await command.ExecuteAsync(console));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that AlarmsCommand rejects zero interval values with a command exception.</summary>
|
||||
[Fact]
|
||||
public async Task AlarmsCommand_ZeroInterval_ThrowsCommandException()
|
||||
{
|
||||
@@ -128,6 +135,7 @@ public class CommandRangeValidationTests
|
||||
ex.Message.ShouldContain("--interval");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that HistoryReadCommand rejects negative max values with a command exception.</summary>
|
||||
[Fact]
|
||||
public async Task HistoryReadCommand_NegativeMax_ThrowsCommandException()
|
||||
{
|
||||
@@ -145,6 +153,7 @@ public class CommandRangeValidationTests
|
||||
ex.Message.ShouldContain("--max");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that HistoryReadCommand rejects zero interval values with a command exception.</summary>
|
||||
[Fact]
|
||||
public async Task HistoryReadCommand_ZeroInterval_ThrowsCommandException()
|
||||
{
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
|
||||
|
||||
public class ConnectCommandTests
|
||||
{
|
||||
/// <summary>Verifies that execute prints connection info.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_PrintsConnectionInfo()
|
||||
{
|
||||
@@ -38,6 +39,7 @@ public class ConnectCommandTests
|
||||
output.ShouldContain("Connection successful.");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that execute calls connect and disconnect.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_CallsConnectAndDisconnect()
|
||||
{
|
||||
@@ -56,6 +58,7 @@ public class ConnectCommandTests
|
||||
fakeService.DisposeCalled.ShouldBeTrue();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that execute disconnects on error.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_DisconnectsOnError()
|
||||
{
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
|
||||
/// </summary>
|
||||
public class EventHandlerLifecycleTests
|
||||
{
|
||||
/// <summary>Verifies that SubscribeCommand detaches the DataChanged event handler after exit.</summary>
|
||||
[Fact]
|
||||
public async Task SubscribeCommand_AfterExit_DataChangedEventHasNoSubscribers()
|
||||
{
|
||||
@@ -35,6 +36,7 @@ public class EventHandlerLifecycleTests
|
||||
"SubscribeCommand must detach its DataChanged handler before returning.");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that AlarmsCommand detaches the AlarmEvent handler after exit.</summary>
|
||||
[Fact]
|
||||
public async Task AlarmsCommand_AfterExit_AlarmEventHasNoSubscribers()
|
||||
{
|
||||
|
||||
@@ -12,27 +12,55 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests.Fakes;
|
||||
public sealed class FakeOpcUaClientService : IOpcUaClientService
|
||||
{
|
||||
// Track calls
|
||||
/// <summary>Gets a value indicating whether ConnectAsync was called.</summary>
|
||||
public bool ConnectCalled { get; private set; }
|
||||
|
||||
/// <summary>Gets the connection settings from the most recent ConnectAsync call.</summary>
|
||||
public ConnectionSettings? LastConnectionSettings { get; private set; }
|
||||
|
||||
/// <summary>Gets a value indicating whether DisconnectAsync was called.</summary>
|
||||
public bool DisconnectCalled { get; private set; }
|
||||
|
||||
/// <summary>Gets a value indicating whether Dispose was called.</summary>
|
||||
public bool DisposeCalled { get; private set; }
|
||||
|
||||
/// <summary>Gets the list of node IDs passed to ReadValueAsync calls.</summary>
|
||||
public List<NodeId> ReadNodeIds { get; } = [];
|
||||
|
||||
/// <summary>Gets the list of (NodeId, value) pairs passed to WriteValueAsync calls.</summary>
|
||||
public List<(NodeId NodeId, object Value)> WriteValues { get; } = [];
|
||||
|
||||
/// <summary>Gets the list of parent node IDs passed to BrowseAsync calls.</summary>
|
||||
public List<NodeId?> BrowseNodeIds { get; } = [];
|
||||
|
||||
/// <summary>Gets the list of (NodeId, intervalMs) pairs from SubscribeAsync calls.</summary>
|
||||
public List<(NodeId NodeId, int IntervalMs)> SubscribeCalls { get; } = [];
|
||||
|
||||
/// <summary>Gets the list of node IDs passed to UnsubscribeAsync calls.</summary>
|
||||
public List<NodeId> UnsubscribeCalls { get; } = [];
|
||||
|
||||
/// <summary>Gets the list of (SourceNodeId, intervalMs) pairs from SubscribeAlarmsAsync calls.</summary>
|
||||
public List<(NodeId? SourceNodeId, int IntervalMs)> SubscribeAlarmsCalls { get; } = [];
|
||||
|
||||
/// <summary>Gets a value indicating whether UnsubscribeAlarmsAsync was called.</summary>
|
||||
public bool UnsubscribeAlarmsCalled { get; private set; }
|
||||
|
||||
/// <summary>Gets a value indicating whether RequestConditionRefreshAsync was called.</summary>
|
||||
public bool RequestConditionRefreshCalled { get; private set; }
|
||||
|
||||
/// <summary>Gets the list of (NodeId, start, end, maxValues) tuples from HistoryReadRawAsync calls.</summary>
|
||||
public List<(NodeId NodeId, DateTime Start, DateTime End, int MaxValues)> HistoryReadRawCalls { get; } = [];
|
||||
|
||||
/// <summary>Gets the list of history read aggregate call parameters.</summary>
|
||||
public List<(NodeId NodeId, DateTime Start, DateTime End, AggregateType Aggregate, double IntervalMs)>
|
||||
HistoryReadAggregateCalls { get; } =
|
||||
[];
|
||||
|
||||
/// <summary>Gets a value indicating whether GetRedundancyInfoAsync was called.</summary>
|
||||
public bool GetRedundancyInfoCalled { get; private set; }
|
||||
|
||||
// Configurable results
|
||||
/// <summary>Gets or sets the connection info returned by ConnectAsync.</summary>
|
||||
public ConnectionInfo ConnectionInfoResult { get; set; } = new(
|
||||
"opc.tcp://localhost:4840",
|
||||
"TestServer",
|
||||
@@ -41,14 +69,17 @@ public sealed class FakeOpcUaClientService : IOpcUaClientService
|
||||
"session-1",
|
||||
"TestSession");
|
||||
|
||||
/// <summary>Gets or sets the data value returned by ReadValueAsync.</summary>
|
||||
public DataValue ReadValueResult { get; set; } = new(
|
||||
new Variant(42),
|
||||
StatusCodes.Good,
|
||||
DateTime.UtcNow,
|
||||
DateTime.UtcNow);
|
||||
|
||||
/// <summary>Gets or sets the status code returned by WriteValueAsync.</summary>
|
||||
public StatusCode WriteStatusCodeResult { get; set; } = StatusCodes.Good;
|
||||
|
||||
/// <summary>Gets or sets the browse results returned by BrowseAsync.</summary>
|
||||
public IReadOnlyList<BrowseResult> BrowseResults { get; set; } = new List<BrowseResult>
|
||||
{
|
||||
new("ns=2;s=Node1", "Node1", "Object", true),
|
||||
@@ -63,19 +94,30 @@ public sealed class FakeOpcUaClientService : IOpcUaClientService
|
||||
/// </summary>
|
||||
public Dictionary<string, IReadOnlyList<BrowseResult>> BrowseResultsByParent { get; } = new();
|
||||
|
||||
/// <summary>Gets or sets the history read result returned by HistoryReadRawAsync and HistoryReadAggregateAsync.</summary>
|
||||
public IReadOnlyList<DataValue> HistoryReadResult { get; set; } = new List<DataValue>
|
||||
{
|
||||
new(new Variant(10.0), StatusCodes.Good, DateTime.UtcNow.AddHours(-1), DateTime.UtcNow),
|
||||
new(new Variant(20.0), StatusCodes.Good, DateTime.UtcNow, DateTime.UtcNow)
|
||||
};
|
||||
|
||||
/// <summary>Gets or sets the redundancy info returned by GetRedundancyInfoAsync.</summary>
|
||||
public RedundancyInfo RedundancyInfoResult { get; set; } = new(
|
||||
"Warm", 200, ["urn:server1", "urn:server2"], "urn:app:test");
|
||||
|
||||
/// <summary>Gets or sets the exception thrown by ConnectAsync.</summary>
|
||||
public Exception? ConnectException { get; set; }
|
||||
|
||||
/// <summary>Gets or sets the exception thrown by ReadValueAsync.</summary>
|
||||
public Exception? ReadException { get; set; }
|
||||
|
||||
/// <summary>Gets or sets the exception thrown by WriteValueAsync.</summary>
|
||||
public Exception? WriteException { get; set; }
|
||||
|
||||
/// <summary>Gets or sets the exception thrown by RequestConditionRefreshAsync.</summary>
|
||||
public Exception? ConditionRefreshException { get; set; }
|
||||
|
||||
/// <summary>Gets or sets the exception thrown by SubscribeAsync.</summary>
|
||||
public Exception? SubscribeException { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -218,18 +260,24 @@ public sealed class FakeOpcUaClientService : IOpcUaClientService
|
||||
}
|
||||
|
||||
/// <summary>Raises the DataChanged event for testing subscribe commands.</summary>
|
||||
/// <param name="nodeId">The node ID string that changed.</param>
|
||||
/// <param name="value">The new data value.</param>
|
||||
public void RaiseDataChanged(string nodeId, DataValue value)
|
||||
{
|
||||
DataChanged?.Invoke(this, new DataChangedEventArgs(nodeId, value));
|
||||
}
|
||||
|
||||
/// <summary>Raises the AlarmEvent for testing alarm commands.</summary>
|
||||
/// <param name="args">The alarm event arguments.</param>
|
||||
public void RaiseAlarmEvent(AlarmEventArgs args)
|
||||
{
|
||||
AlarmEvent?.Invoke(this, args);
|
||||
}
|
||||
|
||||
/// <summary>Raises the ConnectionStateChanged event for testing.</summary>
|
||||
/// <param name="oldState">The previous connection state.</param>
|
||||
/// <param name="newState">The new connection state.</param>
|
||||
/// <param name="endpointUrl">The endpoint URL.</param>
|
||||
public void RaiseConnectionStateChanged(ConnectionState oldState, ConnectionState newState, string endpointUrl)
|
||||
{
|
||||
ConnectionStateChanged?.Invoke(this, new ConnectionStateChangedEventArgs(oldState, newState, endpointUrl));
|
||||
|
||||
@@ -9,11 +9,14 @@ public sealed class FakeOpcUaClientServiceFactory : IOpcUaClientServiceFactory
|
||||
{
|
||||
private readonly FakeOpcUaClientService _service;
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="FakeOpcUaClientServiceFactory"/> class.</summary>
|
||||
/// <param name="service">The fake OPC UA client service to return.</param>
|
||||
public FakeOpcUaClientServiceFactory(FakeOpcUaClientService service)
|
||||
{
|
||||
_service = service;
|
||||
}
|
||||
|
||||
/// <summary>Creates and returns the fake OPC UA client service.</summary>
|
||||
public IOpcUaClientService Create()
|
||||
{
|
||||
return _service;
|
||||
|
||||
@@ -9,6 +9,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
|
||||
|
||||
public class HistoryReadCommandTests
|
||||
{
|
||||
/// <summary>Verifies RawRead execution prints values.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_RawRead_PrintsValues()
|
||||
{
|
||||
@@ -42,6 +43,7 @@ public class HistoryReadCommandTests
|
||||
output.ShouldContain("2 values returned.");
|
||||
}
|
||||
|
||||
/// <summary>Verifies RawRead execution calls HistoryReadRaw.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_RawRead_CallsHistoryReadRaw()
|
||||
{
|
||||
@@ -62,6 +64,7 @@ public class HistoryReadCommandTests
|
||||
fakeService.HistoryReadRawCalls[0].NodeId.Identifier.ShouldBe("HistNode");
|
||||
}
|
||||
|
||||
/// <summary>Verifies AggregateRead execution calls HistoryReadAggregate.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_AggregateRead_CallsHistoryReadAggregate()
|
||||
{
|
||||
@@ -83,6 +86,7 @@ public class HistoryReadCommandTests
|
||||
fakeService.HistoryReadAggregateCalls[0].IntervalMs.ShouldBe(60000);
|
||||
}
|
||||
|
||||
/// <summary>Verifies AggregateRead execution prints aggregate info.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_AggregateRead_PrintsAggregateInfo()
|
||||
{
|
||||
@@ -104,6 +108,7 @@ public class HistoryReadCommandTests
|
||||
output.ShouldContain("7200000");
|
||||
}
|
||||
|
||||
/// <summary>Verifies invalid aggregate throws CommandException.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_InvalidAggregate_ThrowsCommandException()
|
||||
{
|
||||
@@ -123,6 +128,7 @@ public class HistoryReadCommandTests
|
||||
async () => await command.ExecuteAsync(console));
|
||||
}
|
||||
|
||||
/// <summary>Verifies disconnect is called in finally block.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_DisconnectsInFinally()
|
||||
{
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
|
||||
/// </summary>
|
||||
public class InputValidationErrorsTests
|
||||
{
|
||||
/// <summary>Verifies that HistoryReadCommand with invalid start time throws CommandException.</summary>
|
||||
[Fact]
|
||||
public async Task HistoryReadCommand_InvalidStartTime_ThrowsCommandException()
|
||||
{
|
||||
@@ -30,6 +31,7 @@ public class InputValidationErrorsTests
|
||||
ex.Message.ShouldContain("--start");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that HistoryReadCommand with invalid end time throws CommandException.</summary>
|
||||
[Fact]
|
||||
public async Task HistoryReadCommand_InvalidEndTime_ThrowsCommandException()
|
||||
{
|
||||
@@ -47,6 +49,7 @@ public class InputValidationErrorsTests
|
||||
ex.Message.ShouldContain("--end");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that HistoryReadCommand with invalid aggregate throws CommandException.</summary>
|
||||
[Fact]
|
||||
public async Task HistoryReadCommand_InvalidAggregate_ThrowsCommandException()
|
||||
{
|
||||
@@ -64,6 +67,7 @@ public class InputValidationErrorsTests
|
||||
ex.Message.ShouldContain("aggregate", Case.Insensitive);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that ReadCommand with invalid node ID throws CommandException.</summary>
|
||||
[Fact]
|
||||
public async Task ReadCommand_InvalidNodeId_ThrowsCommandException()
|
||||
{
|
||||
@@ -80,6 +84,7 @@ public class InputValidationErrorsTests
|
||||
ex.Message.ShouldContain("node", Case.Insensitive);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that SubscribeCommand with invalid node ID throws CommandException.</summary>
|
||||
[Fact]
|
||||
public async Task SubscribeCommand_InvalidNodeId_ThrowsCommandException()
|
||||
{
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
|
||||
/// </summary>
|
||||
public class LoggerLifecycleTests
|
||||
{
|
||||
/// <summary>Verifies that ConfigureLogging disposes previous logger before reassigning.</summary>
|
||||
[Fact]
|
||||
public async Task ConfigureLogging_DisposesPreviousLogger_BeforeReassigning()
|
||||
{
|
||||
@@ -48,8 +49,12 @@ public class LoggerLifecycleTests
|
||||
|
||||
private sealed class DisposeTrackingSink : ILogEventSink, IDisposable
|
||||
{
|
||||
/// <summary>Gets a value indicating whether the sink has been disposed.</summary>
|
||||
public bool Disposed { get; private set; }
|
||||
/// <summary>Emits a log event.</summary>
|
||||
/// <param name="logEvent">The log event to emit.</param>
|
||||
public void Emit(LogEvent logEvent) { }
|
||||
/// <summary>Disposes the sink and marks it as disposed.</summary>
|
||||
public void Dispose() => Disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,24 +7,28 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
|
||||
|
||||
public class NodeIdParserTests
|
||||
{
|
||||
/// <summary>Verifies that Parse returns null for null input.</summary>
|
||||
[Fact]
|
||||
public void Parse_NullInput_ReturnsNull()
|
||||
{
|
||||
NodeIdParser.Parse(null).ShouldBeNull();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that Parse returns null for empty string input.</summary>
|
||||
[Fact]
|
||||
public void Parse_EmptyString_ReturnsNull()
|
||||
{
|
||||
NodeIdParser.Parse("").ShouldBeNull();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that Parse returns null for whitespace-only input.</summary>
|
||||
[Fact]
|
||||
public void Parse_WhitespaceOnly_ReturnsNull()
|
||||
{
|
||||
NodeIdParser.Parse(" ").ShouldBeNull();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that Parse correctly parses standard NodeId format (ns=2;s=MyNode).</summary>
|
||||
[Fact]
|
||||
public void Parse_StandardStringFormat_ReturnsNodeId()
|
||||
{
|
||||
@@ -34,6 +38,7 @@ public class NodeIdParserTests
|
||||
result.Identifier.ShouldBe("MyNode");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that Parse correctly parses numeric NodeId format (i=85).</summary>
|
||||
[Fact]
|
||||
public void Parse_NumericFormat_ReturnsNodeId()
|
||||
{
|
||||
@@ -42,6 +47,7 @@ public class NodeIdParserTests
|
||||
result.IdType.ShouldBe(IdType.Numeric);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that Parse treats bare numeric input as namespace 0 numeric NodeId.</summary>
|
||||
[Fact]
|
||||
public void Parse_BareNumeric_ReturnsNamespace0NumericNodeId()
|
||||
{
|
||||
@@ -51,6 +57,7 @@ public class NodeIdParserTests
|
||||
result.Identifier.ShouldBe((uint)85);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that Parse trims whitespace padding from input.</summary>
|
||||
[Fact]
|
||||
public void Parse_WithWhitespacePadding_Trims()
|
||||
{
|
||||
@@ -59,24 +66,28 @@ public class NodeIdParserTests
|
||||
result.Identifier.ShouldBe("MyNode");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that Parse throws FormatException for invalid input.</summary>
|
||||
[Fact]
|
||||
public void Parse_InvalidFormat_ThrowsFormatException()
|
||||
{
|
||||
Should.Throw<FormatException>(() => NodeIdParser.Parse("not-a-node-id"));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that ParseRequired throws ArgumentException for null input.</summary>
|
||||
[Fact]
|
||||
public void ParseRequired_NullInput_ThrowsArgumentException()
|
||||
{
|
||||
Should.Throw<ArgumentException>(() => NodeIdParser.ParseRequired(null));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that ParseRequired throws ArgumentException for empty input.</summary>
|
||||
[Fact]
|
||||
public void ParseRequired_EmptyInput_ThrowsArgumentException()
|
||||
{
|
||||
Should.Throw<ArgumentException>(() => NodeIdParser.ParseRequired(""));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that ParseRequired returns a NodeId for valid input.</summary>
|
||||
[Fact]
|
||||
public void ParseRequired_ValidInput_ReturnsNodeId()
|
||||
{
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
|
||||
|
||||
public class ReadCommandTests
|
||||
{
|
||||
/// <summary>Verifies that execute prints the read value.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_PrintsReadValue()
|
||||
{
|
||||
@@ -39,6 +40,7 @@ public class ReadCommandTests
|
||||
output.ShouldContain("Server Time:");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that execute calls read value with correct node ID.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_CallsReadValueWithCorrectNodeId()
|
||||
{
|
||||
@@ -57,6 +59,7 @@ public class ReadCommandTests
|
||||
fakeService.ReadNodeIds[0].Identifier.ShouldBe("MyVariable");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that execute disconnects in finally.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_DisconnectsInFinally()
|
||||
{
|
||||
@@ -75,6 +78,7 @@ public class ReadCommandTests
|
||||
fakeService.DisposeCalled.ShouldBeTrue();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that execute disconnects even on read error.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_DisconnectsEvenOnReadError()
|
||||
{
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
|
||||
|
||||
public class RedundancyCommandTests
|
||||
{
|
||||
/// <summary>Verifies that Execute prints redundancy information correctly.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_PrintsRedundancyInfo()
|
||||
{
|
||||
@@ -34,6 +35,7 @@ public class RedundancyCommandTests
|
||||
output.ShouldContain("Application URI: urn:app:myserver");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that Execute omits the Server URIs section when none are present.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_NoServerUris_OmitsUriSection()
|
||||
{
|
||||
@@ -58,6 +60,7 @@ public class RedundancyCommandTests
|
||||
output.ShouldContain("Application URI: urn:app:standalone");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that Execute calls GetRedundancyInfo on the service.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_CallsGetRedundancyInfo()
|
||||
{
|
||||
@@ -74,6 +77,7 @@ public class RedundancyCommandTests
|
||||
fakeService.GetRedundancyInfoCalled.ShouldBeTrue();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that Execute disconnects and disposes in the finally block.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_DisconnectsInFinally()
|
||||
{
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
|
||||
/// </summary>
|
||||
public class SubscribeCommandSummaryTests
|
||||
{
|
||||
/// <summary>Verifies that nodes with no updates are counted separately from suspects.</summary>
|
||||
[Fact]
|
||||
public async Task Summary_NodeWithNoUpdate_IsCountedAsNeverNotAsNeverWentBad()
|
||||
{
|
||||
@@ -39,6 +40,7 @@ public class SubscribeCommandSummaryTests
|
||||
output.ShouldContain("--- Nodes that never received an update at all ---");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that nodes with only good values are counted as never went bad.</summary>
|
||||
[Fact]
|
||||
public async Task Summary_NodeReceivedOnlyGoodValues_IsCountedAsNeverWentBad()
|
||||
{
|
||||
@@ -70,6 +72,7 @@ public class SubscribeCommandSummaryTests
|
||||
output.ShouldContain("No update received at all: 0");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that nodes with bad values are counted as ever went bad.</summary>
|
||||
[Fact]
|
||||
public async Task Summary_NodeReceivedBadValue_IsCountedAsEverWentBad()
|
||||
{
|
||||
@@ -98,6 +101,7 @@ public class SubscribeCommandSummaryTests
|
||||
output.ShouldContain("NEVER went bad (suspect): 0");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that subscription auto-exits when duration expires.</summary>
|
||||
[Fact]
|
||||
public async Task Duration_ZeroOrPositive_AutoExits()
|
||||
{
|
||||
@@ -124,6 +128,7 @@ public class SubscribeCommandSummaryTests
|
||||
output.ShouldContain("==================== SUMMARY ====================");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that --quiet suppresses updates but prints summary.</summary>
|
||||
[Fact]
|
||||
public async Task Quiet_SuppressesPerUpdateOutputButPrintsSummary()
|
||||
{
|
||||
@@ -154,6 +159,7 @@ public class SubscribeCommandSummaryTests
|
||||
output.ShouldContain("==================== SUMMARY ====================");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that summary is written to disk when summary file is specified.</summary>
|
||||
[Fact]
|
||||
public async Task SummaryFile_WritesSummaryToDisk()
|
||||
{
|
||||
@@ -184,6 +190,7 @@ public class SubscribeCommandSummaryTests
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that recursive flag browses subtree and subscribes every variable.</summary>
|
||||
[Fact]
|
||||
public async Task Recursive_BrowsesSubtreeAndSubscribesEveryVariable()
|
||||
{
|
||||
@@ -222,6 +229,7 @@ public class SubscribeCommandSummaryTests
|
||||
output.ShouldContain("Browsing subtree of ns=2;s=Root");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that subscription failures are handled gracefully.</summary>
|
||||
[Fact]
|
||||
public async Task SubscribeFailure_PrintsFailedMessage_DoesNotCrash()
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
|
||||
|
||||
public class SubscribeCommandTests
|
||||
{
|
||||
/// <summary>Verifies that ExecuteAsync subscribes with the correct parameters.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_SubscribesWithCorrectParameters()
|
||||
{
|
||||
@@ -35,6 +36,7 @@ public class SubscribeCommandTests
|
||||
fakeService.SubscribeCalls[0].NodeId.Identifier.ShouldBe("TestVar");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that ExecuteAsync unsubscribes when cancellation is requested.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_UnsubscribesOnCancellation()
|
||||
{
|
||||
@@ -57,6 +59,7 @@ public class SubscribeCommandTests
|
||||
fakeService.UnsubscribeCalls.Count.ShouldBe(1);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that ExecuteAsync disconnects and disposes in a finally block.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_DisconnectsInFinally()
|
||||
{
|
||||
@@ -80,6 +83,7 @@ public class SubscribeCommandTests
|
||||
fakeService.DisposeCalled.ShouldBeTrue();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that ExecuteAsync prints the correct subscription message.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_PrintsSubscriptionMessage()
|
||||
{
|
||||
|
||||
@@ -18,6 +18,8 @@ public static class TestConsoleHelper
|
||||
/// <summary>
|
||||
/// Reads all text written to the console's standard output.
|
||||
/// </summary>
|
||||
/// <param name="console">The fake console instance.</param>
|
||||
/// <returns>The console output text.</returns>
|
||||
public static string GetOutput(FakeInMemoryConsole console)
|
||||
{
|
||||
console.Output.Flush();
|
||||
@@ -27,6 +29,8 @@ public static class TestConsoleHelper
|
||||
/// <summary>
|
||||
/// Reads all text written to the console's standard error.
|
||||
/// </summary>
|
||||
/// <param name="console">The fake console instance.</param>
|
||||
/// <returns>The console error text.</returns>
|
||||
public static string GetError(FakeInMemoryConsole console)
|
||||
{
|
||||
console.Error.Flush();
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
|
||||
|
||||
public class WriteCommandTests
|
||||
{
|
||||
/// <summary>Verifies that write command executes successfully.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_WritesSuccessfully()
|
||||
{
|
||||
@@ -31,6 +32,7 @@ public class WriteCommandTests
|
||||
output.ShouldContain("Write successful: ns=2;s=MyVar = 100");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that write command reports failure.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_ReportsFailure()
|
||||
{
|
||||
@@ -54,6 +56,7 @@ public class WriteCommandTests
|
||||
output.ShouldContain("Write failed:");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that write command reads current value before writing.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_ReadsCurrentValueThenWrites()
|
||||
{
|
||||
@@ -79,6 +82,7 @@ public class WriteCommandTests
|
||||
fakeService.WriteValues[0].Value.ShouldBeOfType<double>();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that write command disconnects in finally block.</summary>
|
||||
[Fact]
|
||||
public async Task Execute_DisconnectsInFinally()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user