test(opcuaclient): HistoryRead Raw/AtTime/Processed wire tests against in-process server (#622)
Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
This commit is contained in:
+14
-12
@@ -13,19 +13,17 @@ namespace ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests;
|
||||
/// fixture" scaffolds in <c>Driver.OpcUaClient.Tests</c> (Gitea #622). No opc-plc and no Docker: every test
|
||||
/// here runs a real secure-channel + session + subscription exchange over loopback. The driver authenticates
|
||||
/// with the rig's API-key credential so writes carry the <c>WriteOperate</c> role.
|
||||
/// <para>
|
||||
/// HistoryRead is NOT covered here (deferred): the server-side leg needs an <c>IHistorianDataSource</c>
|
||||
/// stub plus a historized-variable rig seam, and the driver's passthrough shapes are unit-tested already.
|
||||
/// </para>
|
||||
/// HistoryRead lives in <see cref="OpcUaClientDriverHistoryWireTests"/>; reconnect/resume in
|
||||
/// <see cref="OpcUaClientDriverReconnectWireTests"/>.
|
||||
/// </summary>
|
||||
[Trait("Category", "Integration")]
|
||||
public sealed class OpcUaClientDriverWireTests
|
||||
{
|
||||
private const string SpeedRef = "Sim/dev1/Speed";
|
||||
private const string RoRef = "Sim/dev1/Counter";
|
||||
internal const string SpeedRef = "Sim/dev1/Speed";
|
||||
internal const string RoRef = "Sim/dev1/Counter";
|
||||
private const string MissingRef = "Sim/dev1/Missing";
|
||||
private const string SpeedId = ServerEventRig.RawDeviceFolder + "/Speed";
|
||||
private const string CounterId = ServerEventRig.RawDeviceFolder + "/Counter";
|
||||
internal const string SpeedId = ServerEventRig.RawDeviceFolder + "/Speed";
|
||||
internal const string CounterId = ServerEventRig.RawDeviceFolder + "/Counter";
|
||||
|
||||
private sealed class RecordingWriteGateway(bool succeed) : IOpcUaNodeWriteGateway
|
||||
{
|
||||
@@ -38,10 +36,12 @@ public sealed class OpcUaClientDriverWireTests
|
||||
}
|
||||
}
|
||||
|
||||
private static RawTagEntry Tag(string rawPath, string nodeId) =>
|
||||
internal static RawTagEntry Tag(string rawPath, string nodeId) =>
|
||||
new(rawPath, JsonSerializer.Serialize(new { nodeId }), WriteIdempotent: true);
|
||||
|
||||
private static OpcUaClientDriver NewDriver(ServerEventRig rig, string id, string? browseRoot = null) =>
|
||||
internal static OpcUaClientDriver NewDriver(
|
||||
ServerEventRig rig, string id, string? browseRoot = null, IReadOnlyList<RawTagEntry>? extraTags = null,
|
||||
TimeSpan? reconnectPeriod = null) =>
|
||||
new(new OpcUaClientDriverOptions
|
||||
{
|
||||
EndpointUrl = rig.EndpointUrl,
|
||||
@@ -50,6 +50,7 @@ public sealed class OpcUaClientDriverWireTests
|
||||
Tag(SpeedRef, ServerEventRig.RawNsu(SpeedId)),
|
||||
Tag(RoRef, ServerEventRig.RawNsu(CounterId)),
|
||||
Tag(MissingRef, ServerEventRig.RawNsu($"{ServerEventRig.RawDeviceFolder}/NoSuchNode")),
|
||||
.. extraTags ?? [],
|
||||
],
|
||||
SecurityPolicy = OpcUaSecurityPolicy.None,
|
||||
SecurityMode = OpcUaSecurityMode.None,
|
||||
@@ -62,9 +63,10 @@ public sealed class OpcUaClientDriverWireTests
|
||||
SessionTimeout = TimeSpan.FromSeconds(30),
|
||||
KeepAliveInterval = TimeSpan.FromSeconds(1),
|
||||
BrowseRoot = browseRoot,
|
||||
ReconnectPeriod = reconnectPeriod ?? TimeSpan.FromSeconds(5),
|
||||
}, id);
|
||||
|
||||
private static async Task<ServerEventRig> StartRigAsync(string name, CancellationToken ct)
|
||||
internal static async Task<ServerEventRig> StartRigAsync(string name, CancellationToken ct)
|
||||
{
|
||||
var rig = await ServerEventRig.StartAsync(name, encrypted: false, ct);
|
||||
rig.EnsureRawVariable("Speed", "Float", writable: true);
|
||||
@@ -72,7 +74,7 @@ public sealed class OpcUaClientDriverWireTests
|
||||
return rig;
|
||||
}
|
||||
|
||||
private static void Publish(ServerEventRig rig, string id, object value) =>
|
||||
internal static void Publish(ServerEventRig rig, string id, object value) =>
|
||||
rig.Sink.WriteValue(id, value, OpcUaStatus.Good, DateTime.UtcNow, AddressSpaceRealm.Raw);
|
||||
|
||||
/// <summary>Reads round-trip through the real wire; a node the server lacks does not read Good.</summary>
|
||||
|
||||
Reference in New Issue
Block a user