From da4634d67ead2aea1ed30c85f2ffb1e51d14603d Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Fri, 29 May 2026 10:19:32 -0400 Subject: [PATCH] fix(tests,cli): implement IOpcUaAddressSpaceSink.EnsureVariable in test fakes; fix CLI CS1587 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolves the 12 reported build errors (7 CS0535 sink fakes + 5 CLI CS1587). Runtime.Tests green (74). NOTE: OpcUaServer.Tests still has pre-existing CS7036 errors from the in-progress Galaxy-tag workstream (Phase7Plan/Phase7CompositionResult new required params) — separate, test-only, not addressed here. --- .../Commands/SubscribeCommand.cs | 6 +++--- .../Commands/ProbeCommand.cs | 4 ++-- .../DeferredAddressSpaceSinkTests.cs | 3 +++ .../Phase7ApplierHierarchyTests.cs | 6 ++++++ .../Phase7ApplierTests.cs | 17 +++++++++++++++++ .../Observability/OtOpcUaTelemetryHookTests.cs | 6 ++++++ .../OpcUa/OpcUaPublishActorRebuildTests.cs | 7 +++++++ .../OpcUa/OpcUaPublishActorTests.cs | 7 +++++++ 8 files changed, 51 insertions(+), 5 deletions(-) diff --git a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Cli/Commands/SubscribeCommand.cs b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Cli/Commands/SubscribeCommand.cs index f4645ef2..429c0a4b 100644 --- a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Cli/Commands/SubscribeCommand.cs +++ b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Cli/Commands/SubscribeCommand.cs @@ -12,20 +12,20 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Cli.Commands; [Command("subscribe", Description = "Watch a PCCC file address via polled subscription until Ctrl+C.")] public sealed class SubscribeCommand : AbLegacyCommandBase { - [CommandOption("address", 'a', Description = "PCCC file address — same format as `read`.", IsRequired = true)] /// Gets or sets the PCCC file address to subscribe to. + [CommandOption("address", 'a', Description = "PCCC file address — same format as `read`.", IsRequired = true)] public string Address { get; init; } = default!; + /// Gets or sets the data type of the address. [CommandOption("type", 't', Description = "Bit / Int / Long / Float / AnalogInt / String / TimerElement / CounterElement / " + "ControlElement (default Int).")] - /// Gets or sets the data type of the address. public AbLegacyDataType DataType { get; init; } = AbLegacyDataType.Int; + /// Gets or sets the polling interval in milliseconds. [CommandOption("interval-ms", 'i', Description = "Publishing interval in milliseconds (default 1000). PollGroupEngine floors " + "sub-250ms values.")] - /// Gets or sets the polling interval in milliseconds. public int IntervalMs { get; init; } = 1000; /// diff --git a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.S7.Cli/Commands/ProbeCommand.cs b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.S7.Cli/Commands/ProbeCommand.cs index f76b4929..4e1aaf23 100644 --- a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.S7.Cli/Commands/ProbeCommand.cs +++ b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.S7.Cli/Commands/ProbeCommand.cs @@ -13,14 +13,14 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.S7.Cli.Commands; [Command("probe", Description = "Verify the S7 endpoint is reachable and a sample read succeeds.")] public sealed class ProbeCommand : S7CommandBase { + /// Gets or sets the S7 address to probe. [CommandOption("address", 'a', Description = "Probe address (default MW0 — merker word 0). DB1.DBW0 if your PLC project " + "reserves a fingerprint DB.")] - /// Gets or sets the S7 address to probe. public string Address { get; init; } = "MW0"; - [CommandOption("type", Description = "Probe data type (default Int16).")] /// Gets or sets the data type of the probe address. + [CommandOption("type", Description = "Probe data type (default Int16).")] public S7DataType DataType { get; init; } = S7DataType.Int16; /// diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/DeferredAddressSpaceSinkTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/DeferredAddressSpaceSinkTests.cs index 25324ace..1961e3c8 100644 --- a/tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/DeferredAddressSpaceSinkTests.cs +++ b/tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/DeferredAddressSpaceSinkTests.cs @@ -84,6 +84,9 @@ public sealed class DeferredAddressSpaceSinkTests public void EnsureFolder(string folderNodeId, string? parentNodeId, string displayName) => CallQueue.Enqueue($"EF:{folderNodeId}"); /// + public void EnsureVariable(string variableNodeId, string? parentFolderNodeId, string displayName, string dataType) + => CallQueue.Enqueue($"EV:{variableNodeId}"); + /// public void RebuildAddressSpace() => CallQueue.Enqueue("RB"); } } diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/Phase7ApplierHierarchyTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/Phase7ApplierHierarchyTests.cs index 316aa466..9f914e9b 100644 --- a/tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/Phase7ApplierHierarchyTests.cs +++ b/tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/Phase7ApplierHierarchyTests.cs @@ -149,6 +149,12 @@ public sealed class Phase7ApplierHierarchyTests : IDisposable /// The display name of the folder. public void EnsureFolder(string folderNodeId, string? parentNodeId, string displayName) => _calls.Enqueue((folderNodeId, parentNodeId, displayName)); + /// Ensures a variable exists (stub implementation for testing). + /// The node ID of the variable. + /// The node ID of the parent folder, or null for root. + /// The display name of the variable. + /// The OPC UA built-in type name. + public void EnsureVariable(string variableNodeId, string? parentFolderNodeId, string displayName, string dataType) { } /// Rebuilds the address space (stub implementation for testing). public void RebuildAddressSpace() { } } diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/Phase7ApplierTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/Phase7ApplierTests.cs index 01c825a5..5d7d02eb 100644 --- a/tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/Phase7ApplierTests.cs +++ b/tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/Phase7ApplierTests.cs @@ -133,6 +133,8 @@ public sealed class Phase7ApplierTests public ConcurrentQueue<(string NodeId, bool Active, bool Acknowledged)> AlarmQueue { get; } = new(); /// Gets the queue of folder creation calls. public ConcurrentQueue<(string NodeId, string? Parent, string DisplayName)> FolderQueue { get; } = new(); + /// Gets the queue of variable creation calls. + public ConcurrentQueue<(string NodeId, string? Parent, string DisplayName, string DataType)> VariableQueue { get; } = new(); /// Gets the number of rebuild calls made on this sink. public int RebuildCalls; @@ -140,6 +142,8 @@ public sealed class Phase7ApplierTests public List<(string NodeId, bool Active, bool Acknowledged)> AlarmWrites => AlarmQueue.ToList(); /// Gets the list of recorded folder creation calls. public List<(string NodeId, string? Parent, string DisplayName)> FolderCalls => FolderQueue.ToList(); + /// Gets the list of recorded variable creation calls. + public List<(string NodeId, string? Parent, string DisplayName, string DataType)> VariableCalls => VariableQueue.ToList(); /// Records a value write (no-op in this recording sink). /// The node ID. @@ -160,6 +164,13 @@ public sealed class Phase7ApplierTests /// The display name for the folder. public void EnsureFolder(string folderNodeId, string? parentNodeId, string displayName) => FolderQueue.Enqueue((folderNodeId, parentNodeId, displayName)); + /// Records a variable creation call. + /// The variable node ID. + /// The parent folder node ID, if any. + /// The display name for the variable. + /// The OPC UA built-in type name. + public void EnsureVariable(string variableNodeId, string? parentFolderNodeId, string displayName, string dataType) + => VariableQueue.Enqueue((variableNodeId, parentFolderNodeId, displayName, dataType)); /// Records a rebuild address space call. public void RebuildAddressSpace() => Interlocked.Increment(ref RebuildCalls); } @@ -192,6 +203,12 @@ public sealed class Phase7ApplierTests /// The parent folder node ID, if any. /// The display name for the folder. public void EnsureFolder(string folderNodeId, string? parentNodeId, string displayName) { } + /// No-op variable creation call. + /// The variable node ID. + /// The parent folder node ID, if any. + /// The display name for the variable. + /// The OPC UA built-in type name. + public void EnsureVariable(string variableNodeId, string? parentFolderNodeId, string displayName, string dataType) { } /// No-op rebuild address space call. public void RebuildAddressSpace() { } } diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Observability/OtOpcUaTelemetryHookTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Observability/OtOpcUaTelemetryHookTests.cs index 8629ffae..62e08ee6 100644 --- a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Observability/OtOpcUaTelemetryHookTests.cs +++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Observability/OtOpcUaTelemetryHookTests.cs @@ -206,6 +206,12 @@ public sealed class OtOpcUaTelemetryHookTests : RuntimeActorTestBase /// The parent folder node identifier. /// The display name for the folder. public void EnsureFolder(string folderNodeId, string? parentNodeId, string displayName) { } + /// Ensures variable exists (stub implementation). + /// The variable node identifier. + /// The parent folder node identifier. + /// The display name for the variable. + /// The OPC UA built-in type name. + public void EnsureVariable(string variableNodeId, string? parentFolderNodeId, string displayName, string dataType) { } /// Rebuilds address space (recorded via span). public void RebuildAddressSpace() { /* recorded via span */ } } diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/OpcUa/OpcUaPublishActorRebuildTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/OpcUa/OpcUaPublishActorRebuildTests.cs index 6e3abb09..618c1672 100644 --- a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/OpcUa/OpcUaPublishActorRebuildTests.cs +++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/OpcUa/OpcUaPublishActorRebuildTests.cs @@ -161,6 +161,13 @@ public sealed class OpcUaPublishActorRebuildTests : RuntimeActorTestBase /// The display name of the folder. public void EnsureFolder(string folderNodeId, string? parentNodeId, string displayName) => Calls.Enqueue($"EF:{folderNodeId}"); + /// Records a variable ensure call. + /// The variable node ID. + /// The parent folder node ID, or null if this is a root variable. + /// The display name of the variable. + /// The OPC UA built-in type name. + public void EnsureVariable(string variableNodeId, string? parentFolderNodeId, string displayName, string dataType) + => Calls.Enqueue($"EV:{variableNodeId}"); /// Records a rebuild address space call. public void RebuildAddressSpace() => Interlocked.Increment(ref RebuildCalls); } diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/OpcUa/OpcUaPublishActorTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/OpcUa/OpcUaPublishActorTests.cs index 00680064..f89033a2 100644 --- a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/OpcUa/OpcUaPublishActorTests.cs +++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/OpcUa/OpcUaPublishActorTests.cs @@ -182,6 +182,13 @@ public sealed class OpcUaPublishActorTests : RuntimeActorTestBase /// The display name of the folder. public void EnsureFolder(string folderNodeId, string? parentNodeId, string displayName) { } + /// Ensures a variable exists (no-op in test). + /// The OPC UA variable node identifier. + /// The parent folder node identifier, or null for root. + /// The display name of the variable. + /// The OPC UA built-in type name. + public void EnsureVariable(string variableNodeId, string? parentFolderNodeId, string displayName, string dataType) { } + /// Records a rebuild call. public void RebuildAddressSpace() => Interlocked.Increment(ref RebuildCalls); }