From a4c61989b21ae87703d5a2eda4001fd7fcfc0dcd Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Wed, 15 Jul 2026 20:59:42 -0400 Subject: [PATCH] test(v3): migrate 6 driver IntegrationTests to RawTags API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace pre-declared options.Tags (typed TagDefinition lists) with options.RawTags (IReadOnlyList) across all 6 Docker-gated driver integration suites so they COMPILE against the v3 driver API. Each project gets a local RawTags helper mirroring the unit-test project's helper: it serialises a typed def back to its TagConfig blob via the driver's TagDefinitionFactory.ToTagConfig and packages it as a RawTagEntry (RawPath = def.Name; DeviceName = def.DeviceHostAddress for the multi-device drivers AbCip/AbLegacy/TwinCAT/FOCAS). Test intent (addresses, data types, device routing, assertions) is unchanged — only the tag-authoring/config-delivery shape was migrated. Docker-gated: these still skip at runtime without fixtures; COMPILE is the gate. --- .../AbCipRawTags.cs | 27 +++++++++++++ .../AbCipReadSmokeTests.cs | 2 +- .../Emulate/AbCipEmulateAlmdTests.cs | 5 +-- .../Emulate/AbCipEmulateUdtReadTests.cs | 5 +-- .../AbLegacyRawTags.cs | 32 +++++++++++++++ .../AbLegacyReadSmokeTests.cs | 10 ++--- .../FocasRawTags.cs | 31 +++++++++++++++ .../Series/WireBackendCoverageTests.cs | 18 ++++----- .../Series/WireBackendTests.cs | 8 ++-- .../AddressingGrammarTests.cs | 4 +- .../DL205/DL205BcdQuirkTests.cs | 5 +-- .../DL205/DL205CoilMappingTests.cs | 2 +- .../DL205/DL205ExceptionCodeTests.cs | 5 +-- .../DL205/DL205FloatCdabQuirkTests.cs | 5 +-- .../DL205/DL205Profile.cs | 5 +-- .../DL205/DL205StringQuirkTests.cs | 5 +-- .../DL205/DL205VMemoryQuirkTests.cs | 10 ++--- .../DL205/DL205XInputTests.cs | 2 +- .../ExceptionInjectionTests.cs | 10 ++--- .../Mitsubishi/MitsubishiProfile.cs | 5 +-- .../Mitsubishi/MitsubishiQuirkTests.cs | 2 +- .../ModbusRawTags.cs | 29 ++++++++++++++ .../S7/S7_1500Profile.cs | 5 +-- .../S7/S7_ByteOrderTests.cs | 15 +++---- .../S7RawTags.cs | 29 ++++++++++++++ .../S7_1500/S7_1500Profile.cs | 6 +-- .../TwinCAT3SmokeTests.cs | 39 +++++++------------ .../TwinCATRawTags.cs | 32 +++++++++++++++ 28 files changed, 249 insertions(+), 104 deletions(-) create mode 100644 tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/AbCipRawTags.cs create mode 100644 tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.IntegrationTests/AbLegacyRawTags.cs create mode 100644 tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.IntegrationTests/FocasRawTags.cs create mode 100644 tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/ModbusRawTags.cs create mode 100644 tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.S7.IntegrationTests/S7RawTags.cs create mode 100644 tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.IntegrationTests/TwinCATRawTags.cs diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/AbCipRawTags.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/AbCipRawTags.cs new file mode 100644 index 00000000..9fed1d68 --- /dev/null +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/AbCipRawTags.cs @@ -0,0 +1,27 @@ +using ZB.MOM.WW.OtOpcUa.Core.Abstractions; + +namespace ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests; + +/// +/// Test helper bridging the pre-v3 pre-declared-tag authoring style (a typed +/// ) to the v3 RawPath seam the driver now consumes +/// (). Each typed def is serialised to its TagConfig blob via +/// , and the def's identity (Name → RawPath), +/// device routing key (DeviceHostAddress) and +/// write-idempotence travel on the entry — exactly the shape the deploy artifact delivers. Lets the +/// driver's integration smoke tests keep expressing fixtures as typed definitions while exercising the +/// v3 RawTagsFromTagConfig table-build path. Mirrors the unit-test project's helper of +/// the same name. +/// +internal static class AbCipRawTags +{ + /// Projects typed definitions to the driver's RawTags option shape. + /// The typed definitions to project. + /// The equivalent list. + public static IReadOnlyList From(params AbCipTagDefinition[] defs) => + [.. defs.Select(d => new RawTagEntry( + RawPath: d.Name, + TagConfig: AbCipTagDefinitionFactory.ToTagConfig(d), + WriteIdempotent: d.WriteIdempotent, + DeviceName: d.DeviceHostAddress))]; +} diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/AbCipReadSmokeTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/AbCipReadSmokeTests.cs index a6b57fa5..51168dfb 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/AbCipReadSmokeTests.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/AbCipReadSmokeTests.cs @@ -37,7 +37,7 @@ public sealed class AbCipReadSmokeTests var drv = new AbCipDriver(new AbCipDriverOptions { Devices = [new AbCipDeviceOptions(deviceUri, profile.Family)], - Tags = [new AbCipTagDefinition("Counter", deviceUri, "TestDINT", AbCipDataType.DInt)], + RawTags = AbCipRawTags.From(new AbCipTagDefinition("Counter", deviceUri, "TestDINT", AbCipDataType.DInt)), Timeout = TimeSpan.FromSeconds(5), }, $"drv-smoke-{profile.Family}"); diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/Emulate/AbCipEmulateAlmdTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/Emulate/AbCipEmulateAlmdTests.cs index 193c475d..d33b464d 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/Emulate/AbCipEmulateAlmdTests.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/Emulate/AbCipEmulateAlmdTests.cs @@ -54,7 +54,7 @@ public sealed class AbCipEmulateAlmdTests Devices = [new AbCipDeviceOptions($"ab://{endpoint}/1,0")], EnableAlarmProjection = true, AlarmPollInterval = TimeSpan.FromMilliseconds(200), - Tags = [ + RawTags = AbCipRawTags.From( new AbCipTagDefinition( Name: "HighTempAlarm", DeviceHostAddress: $"ab://{endpoint}/1,0", @@ -72,8 +72,7 @@ public sealed class AbCipEmulateAlmdTests DeviceHostAddress: $"ab://{endpoint}/1,0", TagPath: "SimulateAlarm", DataType: AbCipDataType.Bool, - Writable: true), - ], + Writable: true)), }; await using var drv = new AbCipDriver(options, driverInstanceId: "emulate-almd"); diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/Emulate/AbCipEmulateUdtReadTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/Emulate/AbCipEmulateUdtReadTests.cs index e36919bd..a6018c02 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/Emulate/AbCipEmulateUdtReadTests.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/Emulate/AbCipEmulateUdtReadTests.cs @@ -51,7 +51,7 @@ public sealed class AbCipEmulateUdtReadTests var options = new AbCipDriverOptions { Devices = [new AbCipDeviceOptions($"ab://{endpoint}/1,0")], - Tags = [ + RawTags = AbCipRawTags.From( new AbCipTagDefinition( Name: "Motor1", DeviceHostAddress: $"ab://{endpoint}/1,0", @@ -61,8 +61,7 @@ public sealed class AbCipEmulateUdtReadTests new AbCipStructureMember("Speed", AbCipDataType.DInt), new AbCipStructureMember("Torque", AbCipDataType.Real), new AbCipStructureMember("Status", AbCipDataType.DInt), - ]), - ], + ])), Timeout = TimeSpan.FromSeconds(5), }; diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.IntegrationTests/AbLegacyRawTags.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.IntegrationTests/AbLegacyRawTags.cs new file mode 100644 index 00000000..ba0babd1 --- /dev/null +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.IntegrationTests/AbLegacyRawTags.cs @@ -0,0 +1,32 @@ +using ZB.MOM.WW.OtOpcUa.Core.Abstractions; + +namespace ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.IntegrationTests; + +/// +/// Test helper bridging the v2 authoring shape (a typed ) to the v3 +/// delivery shape (). Under v3 the driver no longer takes pre-declared +/// definitions — the deploy artifact hands it authored raw tags (RawPath + TagConfig blob + owning +/// DeviceName), and the driver rebuilds the typed definitions via +/// . These integration smoke tests keep expressing their +/// intent as typed definitions; this helper serialises each back to its TagConfig blob (via +/// ) and packages it as a +/// whose RawPath is the def's Name and whose is the def's +/// DeviceHostAddress — so the round-trip through the real mapper reproduces the same definition +/// the test authored, keyed by the same name the read/write/subscribe call sites use and routed to the +/// same device (the driver matches DeviceName against a configured device's Name or HostAddress). +/// Mirrors the unit-test project's helper of the same name. +/// +internal static class AbLegacyRawTags +{ + /// Serialises one typed definition into its (RawPath = def.Name, DeviceName = def.DeviceHostAddress). + /// The typed definition to convert. + /// The equivalent . + public static RawTagEntry Entry(AbLegacyTagDefinition def) + => new(def.Name, AbLegacyTagDefinitionFactory.ToTagConfig(def), def.WriteIdempotent, DeviceName: def.DeviceHostAddress); + + /// Serialises typed definitions into records. + /// The typed definitions to convert (array, params, or a collection expression). + /// The equivalent raw-tag entries. + public static IReadOnlyList Entries(params AbLegacyTagDefinition[] defs) + => [.. defs.Select(Entry)]; +} diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.IntegrationTests/AbLegacyReadSmokeTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.IntegrationTests/AbLegacyReadSmokeTests.cs index 0aa29fc6..313892ce 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.IntegrationTests/AbLegacyReadSmokeTests.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.IntegrationTests/AbLegacyReadSmokeTests.cs @@ -51,13 +51,12 @@ public sealed class AbLegacyReadSmokeTests(AbLegacyServerFixture sim) await using var drv = new AbLegacyDriver(new AbLegacyDriverOptions { Devices = [new AbLegacyDeviceOptions(deviceUri, profile.Family)], - Tags = [ + RawTags = AbLegacyRawTags.Entries( new AbLegacyTagDefinition( Name: "IntCounter", DeviceHostAddress: deviceUri, Address: "N7:0", - DataType: AbLegacyDataType.Int), - ], + DataType: AbLegacyDataType.Int)), Timeout = TimeSpan.FromSeconds(5), Probe = new AbLegacyProbeOptions { Enabled = false }, }, driverInstanceId: $"ablegacy-smoke-{profile.Family}"); @@ -96,14 +95,13 @@ public sealed class AbLegacyReadSmokeTests(AbLegacyServerFixture sim) await using var drv = new AbLegacyDriver(new AbLegacyDriverOptions { Devices = [new AbLegacyDeviceOptions(deviceUri, AbLegacyPlcFamily.Slc500)], - Tags = [ + RawTags = AbLegacyRawTags.Entries( new AbLegacyTagDefinition( Name: "Scratch", DeviceHostAddress: deviceUri, Address: "N7:5", DataType: AbLegacyDataType.Int, - Writable: true), - ], + Writable: true)), Timeout = TimeSpan.FromSeconds(5), Probe = new AbLegacyProbeOptions { Enabled = false }, }, driverInstanceId: "ablegacy-smoke-rw"); diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.IntegrationTests/FocasRawTags.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.IntegrationTests/FocasRawTags.cs new file mode 100644 index 00000000..200d5c6b --- /dev/null +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.IntegrationTests/FocasRawTags.cs @@ -0,0 +1,31 @@ +using ZB.MOM.WW.OtOpcUa.Core.Abstractions; + +namespace ZB.MOM.WW.OtOpcUa.Driver.FOCAS.IntegrationTests; + +/// +/// Test helper bridging the v2 authoring shape (a typed ) to the v3 +/// delivery shape (). Under v3 the driver no longer takes pre-declared +/// definitions — the deploy artifact hands it authored raw tags (RawPath + TagConfig blob + DeviceName), +/// and the driver rebuilds the typed definitions via and routes +/// each to its device by . These integration wire tests keep +/// expressing their intent as typed definitions; this helper serialises each back to its TagConfig blob +/// (via ) and packages it as a +/// whose RawPath is the def's Name and whose DeviceName is the def's DeviceHostAddress — so +/// the round-trip through the real mapper + device match reproduces the same definition the test authored, +/// keyed by the same name the read/write/subscribe call sites use. Mirrors the unit-test project's helper +/// of the same name. +/// +internal static class FocasRawTags +{ + /// Serialises one typed definition into its (RawPath = def.Name, DeviceName = def.DeviceHostAddress). + /// The typed definition to convert. + /// The equivalent . + public static RawTagEntry Entry(FocasTagDefinition def) + => new(def.Name, FocasTagDefinitionFactory.ToTagConfig(def), def.WriteIdempotent, def.DeviceHostAddress); + + /// Serialises typed definitions into records. + /// The typed definitions to convert (array, params, or a collection expression). + /// The equivalent raw-tag entries. + public static IReadOnlyList Entries(params FocasTagDefinition[] defs) + => [.. defs.Select(Entry)]; +} diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.IntegrationTests/Series/WireBackendCoverageTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.IntegrationTests/Series/WireBackendCoverageTests.cs index 1da9f2c6..f09d7e39 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.IntegrationTests/Series/WireBackendCoverageTests.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.IntegrationTests/Series/WireBackendCoverageTests.cs @@ -54,12 +54,10 @@ public sealed class WireBackendCoverageTests var drv = new FocasDriver(new FocasDriverOptions { Devices = [new FocasDeviceOptions(DeviceHost)], - Tags = - [ + RawTags = FocasRawTags.Entries( new FocasTagDefinition("Param6711", DeviceHost, "PARAM:6711", FocasDataType.Int32, Writable: false), new FocasTagDefinition("Macro500", DeviceHost, "MACRO:500", FocasDataType.Float64, Writable: false), - new FocasTagDefinition("R100", DeviceHost, "R100", FocasDataType.Byte, Writable: false), - ], + new FocasTagDefinition("R100", DeviceHost, "R100", FocasDataType.Byte, Writable: false)), Probe = new FocasProbeOptions { Enabled = false }, }, driverInstanceId: "wire-usertags", clientFactory: new WireFocasClientFactory()); @@ -86,11 +84,9 @@ public sealed class WireBackendCoverageTests var drv = new FocasDriver(new FocasDriverOptions { Devices = [new FocasDeviceOptions(DeviceHost, DeviceName: "Lathe-1")], - Tags = - [ + RawTags = FocasRawTags.Entries( new FocasTagDefinition("Run", DeviceHost, "R100", FocasDataType.Byte, Writable: false), - new FocasTagDefinition("Speed", DeviceHost, "MACRO:500", FocasDataType.Float64, Writable: false), - ], + new FocasTagDefinition("Speed", DeviceHost, "MACRO:500", FocasDataType.Float64, Writable: false)), Probe = new FocasProbeOptions { Enabled = false }, }, driverInstanceId: "wire-discover", clientFactory: new WireFocasClientFactory()); @@ -127,7 +123,7 @@ public sealed class WireBackendCoverageTests var drv = new FocasDriver(new FocasDriverOptions { Devices = [new FocasDeviceOptions(DeviceHost)], - Tags = [new FocasTagDefinition("Run", DeviceHost, "R100", FocasDataType.Byte, Writable: false)], + RawTags = FocasRawTags.Entries(new FocasTagDefinition("Run", DeviceHost, "R100", FocasDataType.Byte, Writable: false)), Probe = new FocasProbeOptions { Enabled = false }, }, driverInstanceId: "wire-subscribe", clientFactory: new WireFocasClientFactory()); @@ -172,7 +168,7 @@ public sealed class WireBackendCoverageTests var drv = new FocasDriver(new FocasDriverOptions { Devices = [new FocasDeviceOptions(DeviceHost)], - Tags = [], + RawTags = [], Probe = new FocasProbeOptions { Enabled = false }, AlarmProjection = new FocasAlarmProjectionOptions { @@ -275,7 +271,7 @@ public sealed class WireBackendCoverageTests var driver = new FocasDriver(new FocasDriverOptions { Devices = [new FocasDeviceOptions(DeviceHost, PositionDecimalPlaces: 1)], - Tags = [], + RawTags = [], Probe = new FocasProbeOptions { Enabled = false }, FixedTree = new FocasFixedTreeOptions { diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.IntegrationTests/Series/WireBackendTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.IntegrationTests/Series/WireBackendTests.cs index ec373748..6eff4b42 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.IntegrationTests/Series/WireBackendTests.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.IntegrationTests/Series/WireBackendTests.cs @@ -57,7 +57,7 @@ public sealed class WireBackendTests var driver = new FocasDriver(new FocasDriverOptions { Devices = [new FocasDeviceOptions(DeviceHost)], - Tags = [], + RawTags = [], Probe = new FocasProbeOptions { Enabled = false }, FixedTree = new FocasFixedTreeOptions { @@ -120,7 +120,7 @@ public sealed class WireBackendTests var driver = new FocasDriver(new FocasDriverOptions { Devices = [new FocasDeviceOptions(DeviceHost)], - Tags = [], + RawTags = [], Probe = new FocasProbeOptions { Enabled = false }, FixedTree = new FocasFixedTreeOptions { @@ -175,7 +175,7 @@ public sealed class WireBackendTests var driver = new FocasDriver(new FocasDriverOptions { Devices = [new FocasDeviceOptions(DeviceHost)], - Tags = [], + RawTags = [], Probe = new FocasProbeOptions { Enabled = false }, FixedTree = new FocasFixedTreeOptions { @@ -242,7 +242,7 @@ public sealed class WireBackendTests var driver = new FocasDriver(new FocasDriverOptions { Devices = [new FocasDeviceOptions(DeviceHost)], - Tags = [], + RawTags = [], Probe = new FocasProbeOptions { Enabled = false }, FixedTree = new FocasFixedTreeOptions { diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/AddressingGrammarTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/AddressingGrammarTests.cs index a53ccfb2..2d372eba 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/AddressingGrammarTests.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/AddressingGrammarTests.cs @@ -27,7 +27,7 @@ public sealed class AddressingGrammarTests { var opts = new ModbusDriverOptions { - Host = _sim.Host, Port = _sim.Port, Tags = tags, + Host = _sim.Host, Port = _sim.Port, RawTags = ModbusRawTags.Entries(tags), Probe = new ModbusProbeOptions { Enabled = false }, }; var drv = new ModbusDriver(opts, "addressing-e2e"); @@ -108,7 +108,7 @@ public sealed class AddressingGrammarTests var t3 = new ModbusTagDefinition("T3", ModbusRegion.HoldingRegisters, 204, ModbusDataType.Int16); var opts = new ModbusDriverOptions { - Host = _sim.Host, Port = _sim.Port, Tags = [t1, t2, t3], MaxReadGap = 5, + Host = _sim.Host, Port = _sim.Port, RawTags = ModbusRawTags.Entries([t1, t2, t3]), MaxReadGap = 5, Probe = new ModbusProbeOptions { Enabled = false }, }; var drv = new ModbusDriver(opts, "addressing-e2e"); diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205BcdQuirkTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205BcdQuirkTests.cs index 8fbf8e40..b3ae07e1 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205BcdQuirkTests.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205BcdQuirkTests.cs @@ -31,15 +31,14 @@ public sealed class DL205BcdQuirkTests(ModbusSimulatorFixture sim) Port = sim.Port, UnitId = 1, Timeout = TimeSpan.FromSeconds(2), - Tags = - [ + RawTags = ModbusRawTags.Entries([ new ModbusTagDefinition("DL205_Count_Bcd", ModbusRegion.HoldingRegisters, Address: 1072, DataType: ModbusDataType.Bcd16, Writable: false), new ModbusTagDefinition("DL205_Count_Int16", ModbusRegion.HoldingRegisters, Address: 1072, DataType: ModbusDataType.Int16, Writable: false), - ], + ]), Probe = new ModbusProbeOptions { Enabled = false }, }; await using var driver = new ModbusDriver(options, driverInstanceId: "dl205-bcd"); diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205CoilMappingTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205CoilMappingTests.cs index b77b635f..3b5019b6 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205CoilMappingTests.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205CoilMappingTests.cs @@ -106,7 +106,7 @@ public sealed class DL205CoilMappingTests(ModbusSimulatorFixture sim) Port = sim.Port, UnitId = 1, Timeout = TimeSpan.FromSeconds(2), - Tags = tags, + RawTags = ModbusRawTags.Entries(tags), Probe = new ModbusProbeOptions { Enabled = false }, }; } diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205ExceptionCodeTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205ExceptionCodeTests.cs index 4a7e166f..e7a3773f 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205ExceptionCodeTests.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205ExceptionCodeTests.cs @@ -36,12 +36,11 @@ public sealed class DL205ExceptionCodeTests(ModbusSimulatorFixture sim) Port = sim.Port, UnitId = 1, Timeout = TimeSpan.FromSeconds(2), - Tags = - [ + RawTags = ModbusRawTags.Entries([ new ModbusTagDefinition("Unmapped", ModbusRegion.HoldingRegisters, Address: 16383, DataType: ModbusDataType.UInt16, Writable: false), - ], + ]), Probe = new ModbusProbeOptions { Enabled = false }, }; await using var driver = new ModbusDriver(options, driverInstanceId: "dl205-exc"); diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205FloatCdabQuirkTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205FloatCdabQuirkTests.cs index fecfce23..a90fa677 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205FloatCdabQuirkTests.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205FloatCdabQuirkTests.cs @@ -33,8 +33,7 @@ public sealed class DL205FloatCdabQuirkTests(ModbusSimulatorFixture sim) Port = sim.Port, UnitId = 1, Timeout = TimeSpan.FromSeconds(2), - Tags = - [ + RawTags = ModbusRawTags.Entries([ new ModbusTagDefinition("DL205_Float_CDAB", ModbusRegion.HoldingRegisters, Address: 1056, DataType: ModbusDataType.Float32, Writable: false, @@ -44,7 +43,7 @@ public sealed class DL205FloatCdabQuirkTests(ModbusSimulatorFixture sim) ModbusRegion.HoldingRegisters, Address: 1056, DataType: ModbusDataType.Float32, Writable: false, ByteOrder: ModbusByteOrder.BigEndian), - ], + ]), Probe = new ModbusProbeOptions { Enabled = false }, }; await using var driver = new ModbusDriver(options, driverInstanceId: "dl205-cdab"); diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205Profile.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205Profile.cs index 80b0c08f..5f635de1 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205Profile.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205Profile.cs @@ -37,15 +37,14 @@ public static class DL205Profile Port = port, UnitId = 1, Timeout = TimeSpan.FromSeconds(2), - Tags = - [ + RawTags = ModbusRawTags.Entries([ new ModbusTagDefinition( Name: "Smoke_HReg200", Region: ModbusRegion.HoldingRegisters, Address: SmokeHoldingRegister, DataType: ModbusDataType.Int16, Writable: true), - ], + ]), // Disable the background probe loop — integration tests drive reads explicitly and // the probe would race with assertions. Probe = new ModbusProbeOptions { Enabled = false }, diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205StringQuirkTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205StringQuirkTests.cs index 3614de57..0ff12dbf 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205StringQuirkTests.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205StringQuirkTests.cs @@ -40,8 +40,7 @@ public sealed class DL205StringQuirkTests(ModbusSimulatorFixture sim) Port = sim.Port, UnitId = 1, Timeout = TimeSpan.FromSeconds(2), - Tags = - [ + RawTags = ModbusRawTags.Entries([ new ModbusTagDefinition( Name: "DL205_Hello_Low", Region: ModbusRegion.HoldingRegisters, @@ -60,7 +59,7 @@ public sealed class DL205StringQuirkTests(ModbusSimulatorFixture sim) Writable: false, StringLength: 5, StringByteOrder: ModbusStringByteOrder.HighByteFirst), - ], + ]), Probe = new ModbusProbeOptions { Enabled = false }, }; await using var driver = new ModbusDriver(options, driverInstanceId: "dl205-string"); diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205VMemoryQuirkTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205VMemoryQuirkTests.cs index 7242d680..01c679ef 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205VMemoryQuirkTests.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205VMemoryQuirkTests.cs @@ -36,12 +36,11 @@ public sealed class DL205VMemoryQuirkTests(ModbusSimulatorFixture sim) Port = sim.Port, UnitId = 1, Timeout = TimeSpan.FromSeconds(2), - Tags = - [ + RawTags = ModbusRawTags.Entries([ new ModbusTagDefinition("DL205_V2000", ModbusRegion.HoldingRegisters, Address: pdu, DataType: ModbusDataType.UInt16, Writable: false), - ], + ]), Probe = new ModbusProbeOptions { Enabled = false }, }; await using var driver = new ModbusDriver(options, driverInstanceId: "dl205-vmem"); @@ -75,12 +74,11 @@ public sealed class DL205VMemoryQuirkTests(ModbusSimulatorFixture sim) Port = sim.Port, UnitId = 1, Timeout = TimeSpan.FromSeconds(2), - Tags = - [ + RawTags = ModbusRawTags.Entries([ new ModbusTagDefinition("DL205_V40400", ModbusRegion.HoldingRegisters, Address: pdu, DataType: ModbusDataType.UInt16, Writable: false), - ], + ]), Probe = new ModbusProbeOptions { Enabled = false }, }; await using var driver = new ModbusDriver(options, driverInstanceId: "dl205-sysv"); diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205XInputTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205XInputTests.cs index 201a46a8..41cfa428 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205XInputTests.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/DL205/DL205XInputTests.cs @@ -66,7 +66,7 @@ public sealed class DL205XInputTests(ModbusSimulatorFixture sim) Port = sim.Port, UnitId = 1, Timeout = TimeSpan.FromSeconds(2), - Tags = tags, + RawTags = ModbusRawTags.Entries(tags), Probe = new ModbusProbeOptions { Enabled = false }, }; } diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/ExceptionInjectionTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/ExceptionInjectionTests.cs index 05dee5be..0cb5d767 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/ExceptionInjectionTests.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/ExceptionInjectionTests.cs @@ -47,12 +47,11 @@ public sealed class ExceptionInjectionTests(ModbusSimulatorFixture sim) Port = sim.Port, UnitId = 1, Timeout = TimeSpan.FromSeconds(2), - Tags = - [ + RawTags = ModbusRawTags.Entries([ new ModbusTagDefinition(tagName, ModbusRegion.HoldingRegisters, Address: (ushort)address, DataType: ModbusDataType.UInt16, Writable: false), - ], + ]), Probe = new ModbusProbeOptions { Enabled = false }, }; await using var driver = new ModbusDriver(opts, driverInstanceId: "modbus-exc"); @@ -112,12 +111,11 @@ public sealed class ExceptionInjectionTests(ModbusSimulatorFixture sim) Port = sim.Port, UnitId = 1, Timeout = TimeSpan.FromSeconds(2), - Tags = - [ + RawTags = ModbusRawTags.Entries([ new ModbusTagDefinition(tag, ModbusRegion.HoldingRegisters, Address: (ushort)address, DataType: ModbusDataType.UInt16, Writable: true), - ], + ]), Probe = new ModbusProbeOptions { Enabled = false }, }; await using var driver = new ModbusDriver(opts, driverInstanceId: "modbus-exc-write"); diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/Mitsubishi/MitsubishiProfile.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/Mitsubishi/MitsubishiProfile.cs index f831e5e0..e60ef47d 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/Mitsubishi/MitsubishiProfile.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/Mitsubishi/MitsubishiProfile.cs @@ -32,15 +32,14 @@ public static class MitsubishiProfile Port = port, UnitId = 1, Timeout = TimeSpan.FromSeconds(2), - Tags = - [ + RawTags = ModbusRawTags.Entries([ new ModbusTagDefinition( Name: "Smoke_HReg200", Region: ModbusRegion.HoldingRegisters, Address: SmokeHoldingRegister, DataType: ModbusDataType.Int16, Writable: true), - ], + ]), Probe = new ModbusProbeOptions { Enabled = false }, }; } diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/Mitsubishi/MitsubishiQuirkTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/Mitsubishi/MitsubishiQuirkTests.cs index 8d28ecbc..6b2f1712 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/Mitsubishi/MitsubishiQuirkTests.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/Mitsubishi/MitsubishiQuirkTests.cs @@ -176,7 +176,7 @@ public sealed class MitsubishiQuirkTests(ModbusSimulatorFixture sim) Port = sim.Port, UnitId = 1, Timeout = TimeSpan.FromSeconds(2), - Tags = tags, + RawTags = ModbusRawTags.Entries(tags), Probe = new ModbusProbeOptions { Enabled = false }, }, driverInstanceId: "melsec-quirk"); diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/ModbusRawTags.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/ModbusRawTags.cs new file mode 100644 index 00000000..265ed4bf --- /dev/null +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/ModbusRawTags.cs @@ -0,0 +1,29 @@ +using ZB.MOM.WW.OtOpcUa.Core.Abstractions; + +namespace ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests; + +/// +/// Test helper bridging the v2 authoring shape (a typed ) to the v3 +/// delivery shape (). Under v3 the driver no longer takes pre-declared +/// definitions — the deploy artifact hands it authored raw tags (RawPath + TagConfig blob), and the +/// driver rebuilds the typed definitions via . These integration +/// profiles + quirk tests keep expressing their intent as typed definitions; this helper serialises each +/// back to its TagConfig blob (via ) and packages it +/// as a whose RawPath is the def's Name — so the round-trip through the +/// real mapper reproduces the same definition the test authored, keyed by the same name the +/// read/write/subscribe call sites use. Mirrors the unit-test project's helper of the same name. +/// +internal static class ModbusRawTags +{ + /// Serialises one typed definition into its (RawPath = def.Name). + /// The typed definition to convert. + /// The equivalent . + public static RawTagEntry Entry(ModbusTagDefinition def) + => new(def.Name, ModbusTagDefinitionFactory.ToTagConfig(def), def.WriteIdempotent); + + /// Serialises a sequence of typed definitions into records. + /// The typed definitions to convert. + /// The equivalent raw-tag entries. + public static IReadOnlyList Entries(IEnumerable defs) + => [.. defs.Select(Entry)]; +} diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/S7/S7_1500Profile.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/S7/S7_1500Profile.cs index adfcdac3..0cb75b0a 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/S7/S7_1500Profile.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/S7/S7_1500Profile.cs @@ -32,15 +32,14 @@ public static class S7_1500Profile Port = port, UnitId = 1, Timeout = TimeSpan.FromSeconds(2), - Tags = - [ + RawTags = ModbusRawTags.Entries([ new ModbusTagDefinition( Name: "Smoke_HReg200", Region: ModbusRegion.HoldingRegisters, Address: SmokeHoldingRegister, DataType: ModbusDataType.Int16, Writable: true), - ], + ]), // Disable the background probe loop — integration tests drive reads explicitly and // the probe would race with assertions. Probe = new ModbusProbeOptions { Enabled = false }, diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/S7/S7_ByteOrderTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/S7/S7_ByteOrderTests.cs index f604dbf3..2d3c6c4c 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/S7/S7_ByteOrderTests.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/S7/S7_ByteOrderTests.cs @@ -33,8 +33,7 @@ public sealed class S7_ByteOrderTests(ModbusSimulatorFixture sim) Port = sim.Port, UnitId = 1, Timeout = TimeSpan.FromSeconds(2), - Tags = - [ + RawTags = ModbusRawTags.Entries([ new ModbusTagDefinition("S7_Float_ABCD", ModbusRegion.HoldingRegisters, Address: 100, DataType: ModbusDataType.Float32, Writable: false, @@ -45,7 +44,7 @@ public sealed class S7_ByteOrderTests(ModbusSimulatorFixture sim) ModbusRegion.HoldingRegisters, Address: 100, DataType: ModbusDataType.Float32, Writable: false, ByteOrder: ModbusByteOrder.WordSwap), - ], + ]), Probe = new ModbusProbeOptions { Enabled = false }, }; await using var driver = new ModbusDriver(options, driverInstanceId: "s7-float-abcd"); @@ -79,13 +78,12 @@ public sealed class S7_ByteOrderTests(ModbusSimulatorFixture sim) Port = sim.Port, UnitId = 1, Timeout = TimeSpan.FromSeconds(2), - Tags = - [ + RawTags = ModbusRawTags.Entries([ new ModbusTagDefinition("S7_Int32_ABCD", ModbusRegion.HoldingRegisters, Address: 300, DataType: ModbusDataType.Int32, Writable: false, ByteOrder: ModbusByteOrder.BigEndian), - ], + ]), Probe = new ModbusProbeOptions { Enabled = false }, }; await using var driver = new ModbusDriver(options, driverInstanceId: "s7-int-abcd"); @@ -117,12 +115,11 @@ public sealed class S7_ByteOrderTests(ModbusSimulatorFixture sim) Port = sim.Port, UnitId = 1, Timeout = TimeSpan.FromSeconds(2), - Tags = - [ + RawTags = ModbusRawTags.Entries([ new ModbusTagDefinition("S7_Fingerprint", ModbusRegion.HoldingRegisters, Address: 0, DataType: ModbusDataType.UInt16, Writable: false), - ], + ]), Probe = new ModbusProbeOptions { Enabled = false }, }; await using var driver = new ModbusDriver(options, driverInstanceId: "s7-fingerprint"); diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.S7.IntegrationTests/S7RawTags.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.S7.IntegrationTests/S7RawTags.cs new file mode 100644 index 00000000..aba103da --- /dev/null +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.S7.IntegrationTests/S7RawTags.cs @@ -0,0 +1,29 @@ +using ZB.MOM.WW.OtOpcUa.Core.Abstractions; + +namespace ZB.MOM.WW.OtOpcUa.Driver.S7.IntegrationTests; + +/// +/// Test helper bridging the v2 authoring shape (a typed ) to the v3 +/// delivery shape (). Under v3 the driver no longer takes pre-declared +/// definitions — the deploy artifact hands it authored raw tags (RawPath + TagConfig blob), and the +/// driver rebuilds the typed definitions via . These integration +/// profiles keep expressing their intent as typed definitions; this helper serialises each back to its +/// TagConfig blob (via ) and packages it as a +/// whose RawPath is the def's Name — so the round-trip through the real +/// mapper reproduces the same definition the profile authored, keyed by the same name the +/// read/write/subscribe call sites use. Mirrors the unit-test project's helper of the same name. +/// +internal static class S7RawTags +{ + /// Serialises one typed definition into its (RawPath = def.Name). + /// The typed definition to convert. + /// The equivalent . + public static RawTagEntry Entry(S7TagDefinition def) + => new(def.Name, S7TagDefinitionFactory.ToTagConfig(def), def.WriteIdempotent); + + /// Serialises a sequence of typed definitions into records. + /// The typed definitions to convert. + /// The equivalent raw-tag entries. + public static IReadOnlyList Entries(params S7TagDefinition[] defs) + => [.. defs.Select(Entry)]; +} diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.S7.IntegrationTests/S7_1500/S7_1500Profile.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.S7.IntegrationTests/S7_1500/S7_1500Profile.cs index c329e472..f840686e 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.S7.IntegrationTests/S7_1500/S7_1500Profile.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.S7.IntegrationTests/S7_1500/S7_1500Profile.cs @@ -41,14 +41,12 @@ public static class S7_1500Profile // gate, injecting flakiness that has nothing to do with the code // under test. Probe = new S7ProbeOptions { Enabled = false }, - Tags = - [ + RawTags = S7RawTags.Entries( new S7TagDefinition(ProbeTag, "DB1.DBW0", S7DataType.UInt16), new S7TagDefinition(SmokeI16Tag, "DB1.DBW10", S7DataType.Int16), new S7TagDefinition(SmokeI32Tag, "DB1.DBD20", S7DataType.Int32), new S7TagDefinition(SmokeF32Tag, "DB1.DBD30", S7DataType.Float32), new S7TagDefinition(SmokeBoolTag, "DB1.DBX50.3", S7DataType.Bool), - new S7TagDefinition(WriteScratchTag, "DB1.DBW100", S7DataType.UInt16), - ], + new S7TagDefinition(WriteScratchTag, "DB1.DBW100", S7DataType.UInt16)), }; } diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.IntegrationTests/TwinCAT3SmokeTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.IntegrationTests/TwinCAT3SmokeTests.cs index a5f46f30..f6510e01 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.IntegrationTests/TwinCAT3SmokeTests.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.IntegrationTests/TwinCAT3SmokeTests.cs @@ -246,14 +246,12 @@ public sealed class TwinCAT3SmokeTests(TwinCATXarFixture sim) var options = new TwinCATDriverOptions { Devices = [new TwinCATDeviceOptions($"ads://{sim.TargetNetId}:{sim.AmsPort}", "XAR-VM")], - Tags = - [ + RawTags = TwinCATRawTags.Entries( new TwinCATTagDefinition( Name: "Primitive", DeviceHostAddress: $"ads://{sim.TargetNetId}:{sim.AmsPort}", SymbolPath: symbolPath, - DataType: type), - ], + DataType: type)), Timeout = TimeSpan.FromSeconds(5), Probe = new TwinCATProbeOptions { Enabled = false }, }; @@ -307,8 +305,7 @@ public sealed class TwinCAT3SmokeTests(TwinCATXarFixture sim) var options = new TwinCATDriverOptions { Devices = [new TwinCATDeviceOptions($"ads://{sim.TargetNetId}:{sim.AmsPort}", "XAR-VM")], - Tags = - [ + RawTags = TwinCATRawTags.Entries( new TwinCATTagDefinition( Name: "WordBit3", DeviceHostAddress: $"ads://{sim.TargetNetId}:{sim.AmsPort}", @@ -318,8 +315,7 @@ public sealed class TwinCAT3SmokeTests(TwinCATXarFixture sim) Name: "WordBit4", DeviceHostAddress: $"ads://{sim.TargetNetId}:{sim.AmsPort}", SymbolPath: "GVL_Primitives.vWord.4", - DataType: TwinCATDataType.Bool), - ], + DataType: TwinCATDataType.Bool)), Timeout = TimeSpan.FromSeconds(5), Probe = new TwinCATProbeOptions { Enabled = false }, }; @@ -345,8 +341,7 @@ public sealed class TwinCAT3SmokeTests(TwinCATXarFixture sim) var options = new TwinCATDriverOptions { Devices = [new TwinCATDeviceOptions($"ads://{sim.TargetNetId}:{sim.AmsPort}", "XAR-VM")], - Tags = - [ + RawTags = TwinCATRawTags.Entries( new TwinCATTagDefinition( Name: "MotorTemp", DeviceHostAddress: $"ads://{sim.TargetNetId}:{sim.AmsPort}", @@ -356,8 +351,7 @@ public sealed class TwinCAT3SmokeTests(TwinCATXarFixture sim) Name: "MotorRunning", DeviceHostAddress: $"ads://{sim.TargetNetId}:{sim.AmsPort}", SymbolPath: "GVL_Plant.Line1.Stations[1].Axes[1].Motor.Running", - DataType: TwinCATDataType.Bool), - ], + DataType: TwinCATDataType.Bool)), Timeout = TimeSpan.FromSeconds(5), Probe = new TwinCATProbeOptions { Enabled = false }, }; @@ -386,8 +380,7 @@ public sealed class TwinCAT3SmokeTests(TwinCATXarFixture sim) var options = new TwinCATDriverOptions { Devices = [new TwinCATDeviceOptions($"ads://{sim.TargetNetId}:{sim.AmsPort}", "XAR-VM")], - Tags = - [ + RawTags = TwinCATRawTags.Entries( new TwinCATTagDefinition( Name: "NonexistentSymbol", DeviceHostAddress: $"ads://{sim.TargetNetId}:{sim.AmsPort}", @@ -398,8 +391,7 @@ public sealed class TwinCAT3SmokeTests(TwinCATXarFixture sim) DeviceHostAddress: $"ads://{sim.TargetNetId}:{sim.AmsPort}", SymbolPath: "GVL_Fixture.nCounter", DataType: TwinCATDataType.DInt, - Writable: false), - ], + Writable: false)), Timeout = TimeSpan.FromSeconds(5), Probe = new TwinCATProbeOptions { Enabled = false }, }; @@ -442,8 +434,7 @@ public sealed class TwinCAT3SmokeTests(TwinCATXarFixture sim) new TwinCATDeviceOptions(realHost, "Real-VM"), new TwinCATDeviceOptions(ghostHost, "Ghost-VM"), ], - Tags = - [ + RawTags = TwinCATRawTags.Entries( new TwinCATTagDefinition( Name: "RealCounter", DeviceHostAddress: realHost, @@ -453,8 +444,7 @@ public sealed class TwinCAT3SmokeTests(TwinCATXarFixture sim) Name: "GhostCounter", DeviceHostAddress: ghostHost, SymbolPath: "GVL_Fixture.nCounter", - DataType: TwinCATDataType.DInt), - ], + DataType: TwinCATDataType.DInt)), // Shorter timeout so the bogus device fails fast rather than dragging the whole // test; the healthy read shouldn't be slowed down by a peer timeout. Timeout = TimeSpan.FromSeconds(2), @@ -488,7 +478,7 @@ public sealed class TwinCAT3SmokeTests(TwinCATXarFixture sim) var options = new TwinCATDriverOptions { Devices = [new TwinCATDeviceOptions($"ads://{sim.TargetNetId}:{sim.AmsPort}", "XAR-VM")], - Tags = [], + RawTags = [], Timeout = TimeSpan.FromSeconds(5), Probe = new TwinCATProbeOptions { @@ -532,7 +522,7 @@ public sealed class TwinCAT3SmokeTests(TwinCATXarFixture sim) var options = new TwinCATDriverOptions { Devices = baseOptions.Devices, - Tags = baseOptions.Tags, + RawTags = baseOptions.RawTags, UseNativeNotifications = baseOptions.UseNativeNotifications, Timeout = baseOptions.Timeout, Probe = baseOptions.Probe, @@ -565,7 +555,7 @@ public sealed class TwinCAT3SmokeTests(TwinCATXarFixture sim) HostAddress: $"ads://{sim.TargetNetId}:{sim.AmsPort}", DeviceName: "XAR-VM"), ], - Tags = [ + RawTags = TwinCATRawTags.Entries( new TwinCATTagDefinition( Name: "Counter", DeviceHostAddress: $"ads://{sim.TargetNetId}:{sim.AmsPort}", @@ -582,8 +572,7 @@ public sealed class TwinCAT3SmokeTests(TwinCATXarFixture sim) DeviceHostAddress: $"ads://{sim.TargetNetId}:{sim.AmsPort}", SymbolPath: "GVL_Arrays.aReal1D[5]", DataType: TwinCATDataType.Real, - Writable: true), - ], + Writable: true)), UseNativeNotifications = true, Timeout = TimeSpan.FromSeconds(5), // Disable the probe loop — the smoke tests run their own reads; a background diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.IntegrationTests/TwinCATRawTags.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.IntegrationTests/TwinCATRawTags.cs new file mode 100644 index 00000000..0e01eaa8 --- /dev/null +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.IntegrationTests/TwinCATRawTags.cs @@ -0,0 +1,32 @@ +using ZB.MOM.WW.OtOpcUa.Core.Abstractions; + +namespace ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.IntegrationTests; + +/// +/// Test helper bridging the v2 authoring shape (a typed ) to the v3 +/// delivery shape (). Under v3 the driver no longer takes pre-declared +/// definitions — the deploy artifact hands it authored raw tags (RawPath + TagConfig blob + owning +/// DeviceName), and the driver rebuilds the typed definitions via . +/// These integration smoke tests keep expressing their intent as typed definitions; this helper serialises +/// each back to its TagConfig blob (via ) and packages +/// it as a whose RawPath is the def's Name and whose +/// is the def's DeviceHostAddress — so the round-trip through +/// the real mapper + the driver's device resolution (which matches DeviceName against the configured +/// devices by host) reproduces the same definition + device routing the test authored, keyed by the same +/// name the read/write/subscribe call sites use. Mirrors the unit-test project's helper of the same name. +/// +internal static class TwinCATRawTags +{ + /// Serialises one typed definition into its + /// (RawPath = def.Name, DeviceName = def.DeviceHostAddress). + /// The typed definition to convert. + /// The equivalent . + public static RawTagEntry Entry(TwinCATTagDefinition def) + => new(def.Name, TwinCATTagDefinitionFactory.ToTagConfig(def), def.WriteIdempotent, def.DeviceHostAddress); + + /// Serialises typed definitions into records. + /// The typed definitions to convert (array, params, or a collection expression). + /// The equivalent raw-tag entries. + public static IReadOnlyList Entries(params TwinCATTagDefinition[] defs) + => [.. defs.Select(Entry)]; +}