using System.Text.Json; using ZB.MOM.WW.OtOpcUa.Core.Abstractions; using ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient; namespace ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.IntegrationTests; /// /// Driver-side configuration + well-known opc-plc node identifiers that the smoke /// tests address. Node IDs are stable across opc-plc releases — the simulator /// guarantees the same ns=3;s=... names shipped since v1.0. If a release /// bump breaks these, the fixture's pinned image tag needs a coordinated bump. /// These tests address the driver by RawPath, not by node id (fixed 2026-07-28). v3 /// made the driver resolve every read/write/subscribe reference through its authored /// table — a bare ns=3;s=StepUp is no longer a /// reference the driver accepts, and one that does not resolve is failed LOCALLY as /// BadNodeIdInvalid with no wire round-trip. The smoke tests still passed bare node ids, so all /// three had been failing against a perfectly healthy simulator. Seeding RawTags here is what /// makes them exercise the driver instead of its unresolved-reference guard. /// public static class OpcPlcProfile { /// opc-plc monotonically-increasing UInt32; ticks once per second under default opts. public const string StepUp = "ns=3;s=StepUp"; /// opc-plc random Int32 node; new value ~every 100ms. public const string RandomSignedInt32 = "ns=3;s=RandomSignedInt32"; /// opc-plc alternating boolean; flips every second. public const string AlternatingBoolean = "ns=3;s=AlternatingBoolean"; /// opc-plc fast uint node — ticks every 100ms. Used for subscription-cadence tests. public const string FastUInt1 = "ns=3;s=FastUInt1"; /// The RawPath the smoke tests address by. public const string StepUpRef = "Sim/OpcUaClient/plc/StepUp"; /// The RawPath the smoke tests address by. public const string RandomSignedInt32Ref = "Sim/OpcUaClient/plc/RandomSignedInt32"; /// The RawPath the smoke tests address by. public const string AlternatingBooleanRef = "Sim/OpcUaClient/plc/AlternatingBoolean"; /// The RawPath the smoke tests address by. public const string FastUInt1Ref = "Sim/OpcUaClient/plc/FastUInt1"; /// The authored raw-tag table the driver resolves the *Ref RawPaths through — the /// same {"nodeId": …} TagConfig shape the deploy artifact delivers. public static IReadOnlyList RawTags { get; } = [ Entry(StepUpRef, StepUp), Entry(RandomSignedInt32Ref, RandomSignedInt32), Entry(AlternatingBooleanRef, AlternatingBoolean), Entry(FastUInt1Ref, FastUInt1), ]; private static RawTagEntry Entry(string rawPath, string nodeId) => new(rawPath, JsonSerializer.Serialize(new { nodeId }), WriteIdempotent: true); /// Builds driver options for the OPC PLC endpoint. /// The endpoint URL of the OPC PLC simulator. /// Configured driver options for the OPC PLC. public static OpcUaClientDriverOptions BuildOptions(string endpointUrl) => new() { RawTags = RawTags, EndpointUrl = endpointUrl, SecurityPolicy = OpcUaSecurityPolicy.None, SecurityMode = OpcUaSecurityMode.None, AuthType = OpcUaAuthType.Anonymous, // opc-plc auto-accepts client certs (--aa) but we still present one; trust the // server's cert back since the simulator regenerates it each container spin-up // and there's no meaningful chain to validate against. AutoAcceptCertificates = true, Timeout = TimeSpan.FromSeconds(10), SessionTimeout = TimeSpan.FromSeconds(30), // opc-plc's standard address space mirrors verbatim — treat it as SystemPlatform so // §8 namespace validation passes without requiring a UNS mapping table. TargetNamespaceKind = OpcUaTargetNamespaceKind.SystemPlatform, }; }