diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Tests/GatewayBoundingValueTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Tests/GatewayBoundingValueTests.cs index 0b855923..40979a0c 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Tests/GatewayBoundingValueTests.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Tests/GatewayBoundingValueTests.cs @@ -114,7 +114,7 @@ public sealed class GatewayBoundingValueTests { var bound = await HistoryBounds.StartBoundAsync(Source(Aveva()), "T", At(-30), reverse: false, 65536, Now, Ct); - bound!.StatusCode.ShouldBe(Opc.Ua.StatusCodes.BadBoundNotFound); + bound!.StatusCode.ShouldBe(Opc.Ua.StatusCodes.BadBoundNotFound.Code); bound.SourceTimestampUtc.ShouldBe(At(-30)); bound.Value.ShouldBeNull(); } @@ -134,7 +134,7 @@ public sealed class GatewayBoundingValueTests after.Value.ShouldBe(5d); var missing = await HistoryBounds.EndBoundAsync(source, "T", HistoryBounds.For(At(0), At(101)), At(100), 65536, Now, Ct); - missing.StatusCode.ShouldBe(Opc.Ua.StatusCodes.BadBoundNotFound); + missing.StatusCode.ShouldBe(Opc.Ua.StatusCodes.BadBoundNotFound.Code); missing.SourceTimestampUtc.ShouldBe(At(101)); } @@ -156,7 +156,7 @@ public sealed class GatewayBoundingValueTests var calls = fake.ReadRawCallCount; var beyond = Now.AddDays(3); var missing = await HistoryBounds.EndBoundAsync(source, "T", HistoryBounds.For(At(0), beyond), At(100), 65536, Now, Ct); - missing.StatusCode.ShouldBe(Opc.Ua.StatusCodes.BadBoundNotFound); + missing.StatusCode.ShouldBe(Opc.Ua.StatusCodes.BadBoundNotFound.Code); missing.SourceTimestampUtc.ShouldBe(beyond); fake.ReadRawCallCount.ShouldBe(calls, "a bound beyond the horizon is not found without a read"); source.GetHealthSnapshot().TotalFailures.ShouldBe(0); diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Tests/GatewayCeilingPagingTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Tests/GatewayCeilingPagingTests.cs index 374147a6..c4c6afc9 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Tests/GatewayCeilingPagingTests.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Tests/GatewayCeilingPagingTests.cs @@ -106,7 +106,7 @@ public sealed class GatewayCeilingPagingTests : IDisposable try { var first = ReadRaw(nm, nodeId, At(0), At(3600), 5000, null); - first.Error.StatusCode.Code.ShouldBe(StatusCodes.Good); + first.Error.StatusCode.ShouldBe(StatusCodes.Good); first.Values.Count.ShouldBe(FirstPage); first.Cp.ShouldNotBeNull(); // The budget the client asked for (+ lookahead + allowance, refused naming 1000), the ceiling re-read that cannot @@ -114,7 +114,7 @@ public sealed class GatewayCeilingPagingTests : IDisposable fake.RawCalls.Select(c => c.MaxValues).ShouldBe([5000 + 1 + RawAggregateReader.PreWindowAllowance, Ceiling, Ceiling]); var (rest, _, status) = DrainFrom(nm, nodeId, At(0), At(3600), 5000, first.Cp); - status.Code.ShouldBe(StatusCodes.Good); + status.ShouldBe(StatusCodes.Good); first.Values.Concat(rest).ShouldBe(PerSecond(3600).Select(s => s.Item2)); Refusals(fake).ShouldBe(1); } @@ -140,7 +140,7 @@ public sealed class GatewayCeilingPagingTests : IDisposable ? DrainFrom(nm, nodeId, At(3600), At(-1), n, null) : DrainFrom(nm, nodeId, At(0), At(3600), n, null); - status.Code.ShouldBe(StatusCodes.Good); + status.ShouldBe(StatusCodes.Good); var expected = stored.Select(s => s.Item2); values.ShouldBe(reverse ? expected.Reverse() : expected); pages[0].ShouldBe(FirstPage); @@ -217,10 +217,10 @@ public sealed class GatewayCeilingPagingTests : IDisposable var (values, pages, status) = DrainFrom(nm, nodeId, At(0), At(5000), n, null, maxPages: 60); var expected = stored.Select(s => s.Item2).ToList(); - if (status.Code == StatusCodes.Good) values.ShouldBe(expected); + if (status == StatusCodes.Good) values.ShouldBe(expected); else { - status.Code.ShouldBe(StatusCodes.BadTooManyOperations); + status.ShouldBe(StatusCodes.BadTooManyOperations); values.ShouldBe(expected.Take(values.Count)); // an exact prefix size.ShouldBeGreaterThan(L - 2, "a cluster that fits the over-fetch is always served"); } @@ -254,7 +254,7 @@ public sealed class GatewayCeilingPagingTests : IDisposable ds.MaxRawValuesPerRead.ShouldBe(0); var (rest, pages, status) = DrainFrom(nm, nodeId, At(0), At(5000), 0, first.Cp, maxPages: 20); - status.Code.ShouldBe(StatusCodes.Good); + status.ShouldBe(StatusCodes.Good); first.Values.Concat(rest).ShouldBe(stored.Select(s => s.Item2)); pages.Count.ShouldBeLessThan(20); } @@ -278,7 +278,7 @@ public sealed class GatewayCeilingPagingTests : IDisposable fake.MaxValuesCeiling = 500; // the operator lowered it fake.RawCalls.Clear(); var (rest, pages, status) = DrainFrom(nm, nodeId, At(0), At(3600), 5000, p2.Cp, maxPages: 20); - status.Code.ShouldBe(StatusCodes.Good); + status.ShouldBe(StatusCodes.Good); got.AddRange(rest); got.ShouldBe(stored.Select(s => s.Item2)); pages.ShouldAllBe(p => p <= 500 - RawAggregateReader.PreWindowAllowance); @@ -302,7 +302,7 @@ public sealed class GatewayCeilingPagingTests : IDisposable var start = At(10).AddMilliseconds(500); var end = At(3000).AddMilliseconds(500); var (values, pages, status) = DrainFrom(nm, nodeId, start, end, 5000, null, returnBounds: true); - status.Code.ShouldBe(StatusCodes.Good); + status.ShouldBe(StatusCodes.Good); values.ShouldBe(Enumerable.Range(10, 2992).Select(i => (double)i)); pages.ShouldAllBe(p => p <= L); Refusals(fake).ShouldBe(0); @@ -325,7 +325,7 @@ public sealed class GatewayCeilingPagingTests : IDisposable try { var r = ReadRaw(nm, nodeId, DateTime.MinValue, T0.AddMilliseconds(200_000), n, null); - r.Error.StatusCode.Code.ShouldBe(StatusCodes.Good); + r.Error.StatusCode.ShouldBe(StatusCodes.Good); r.Cp.ShouldNotBeNull(); var page = ceiling - RawAggregateReader.PreWindowAllowance - 1; r.Values.ShouldBe(Enumerable.Range(200_000 - r.Values.Count, r.Values.Count).Reverse().Select(i => (double)i)); @@ -360,7 +360,7 @@ public sealed class GatewayCeilingPagingTests : IDisposable try { var (values, pages, status) = DrainFrom(nm, nodeId, DateTime.UnixEpoch, DateTime.UnixEpoch.AddDays(1), 0, null); - status.Code.ShouldBe(StatusCodes.Good); + status.ShouldBe(StatusCodes.Good); values.ShouldBe(stored.Select(s => s.Item2)); pages.Count.ShouldBeGreaterThan(1); } @@ -377,7 +377,7 @@ public sealed class GatewayCeilingPagingTests : IDisposable { ReadRaw(nm, nodeId, DateTime.UnixEpoch, DateTime.UnixEpoch.AddSeconds(5), 5000, null); // learns the ceiling var r = ReadRaw(nm, nodeId, DateTime.MinValue, DateTime.UnixEpoch.AddDays(30), 10, null); - r.Error.StatusCode.Code.ShouldBe(StatusCodes.Good); + r.Error.StatusCode.ShouldBe(StatusCodes.Good); r.Values.ShouldBe(Enumerable.Range(2991, 10).Reverse().Select(i => (double)i)); // the LATEST ten, newest first } finally { await host.DisposeAsync(); } @@ -425,7 +425,7 @@ public sealed class GatewayCeilingPagingTests : IDisposable fake.RawCalls.Clear(); var (values, _, status) = DrainFrom(nm, nodeId, At(0), x.AddDays(1), n, null); - status.Code.ShouldBe(StatusCodes.Good); + status.ShouldBe(StatusCodes.Good); values.ShouldBe(stored.Select(s => s.Item2)); Refusals(fake).ShouldBe(0); EveryRequestFits(fake); @@ -476,7 +476,7 @@ public sealed class GatewayCeilingPagingTests : IDisposable try { var r = ReadRaw(nm, nodeId, At(0), At(10), 10, null); - r.Error.StatusCode.Code.ShouldBe(StatusCodes.BadNoCommunication); + r.Error.StatusCode.ShouldBe(StatusCodes.BadNoCommunication); } finally { await host.DisposeAsync(); } } @@ -528,7 +528,7 @@ public sealed class GatewayCeilingPagingTests : IDisposable private static (IReadOnlyList Values, ServiceResult Error, byte[]? Cp) ReadRaw( OtOpcUaNodeManager nm, NodeId nodeId, DateTime start, DateTime end, uint max, byte[]? inboundCp, bool returnBounds = false) { - var context = new OperationContext(new RequestHeader(), secureChannelContext: null, RequestType.HistoryRead, identity: null); + var context = new OperationContext(new RequestHeader(), secureChannelContext: null, RequestType.HistoryRead, requestLifetime: RequestLifetime.None, identity: null); var details = new ReadRawModifiedDetails { ReturnBounds = returnBounds, @@ -537,16 +537,19 @@ public sealed class GatewayCeilingPagingTests : IDisposable EndTime = end, NumValuesPerNode = max, }; - var nodesToRead = new List { new() { NodeId = nodeId, ContinuationPoint = inboundCp } }; + var nodesToRead = new List { new() { NodeId = nodeId, ContinuationPoint = inboundCp is null ? default : ByteString.From(inboundCp) } }; var results = new List { null! }; var errors = new List { null! }; nm.HistoryRead(context, details, TimestampsToReturn.Both, releaseContinuationPoints: false, nodesToRead, results, errors); var values = new List(); - if (results[0]?.HistoryData is { } ho && !ExtensionObject.IsNull(ho)) - foreach (var dv in ((HistoryData)ExtensionObject.ToEncodeable(ho)).DataValues) - values.Add(Convert.ToDouble(dv.Value)); - return (values, errors[0], results[0]?.ContinuationPoint); + if (results[0]?.HistoryData is { IsNull: false } historyData) + { + var data = (HistoryData)ExtensionObject.ToEncodeable(historyData)!; + foreach (var dv in data.DataValues) + values.Add(Convert.ToDouble(SdkValueBoundary.ToClr(dv.WrappedValue))); + } + return (values, errors[0], results[0]?.ContinuationPoint is { IsNull: false } cp ? cp.ToArray() : null); } public void Dispose() diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Tests/GatewayRawCapTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Tests/GatewayRawCapTests.cs index c1c5da7f..91ae847e 100644 --- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Tests/GatewayRawCapTests.cs +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Tests/GatewayRawCapTests.cs @@ -205,7 +205,7 @@ public sealed class GatewayRawCapTests : IDisposable ? DrainFrom(nm, nodeId, At(3600), At(-1), n, null) : DrainFrom(nm, nodeId, At(0), At(3600), n, null); - status.Code.ShouldBe(StatusCodes.Good); + status.ShouldBe(StatusCodes.Good); var expected = Enumerable.Range(0, 3600).Select(i => (double)i); values.ShouldBe(reverse ? expected.Reverse() : expected); pages.Count.ShouldBeGreaterThan(1, "a year-sized window at N = 0 is paged, not one shot"); @@ -224,7 +224,7 @@ public sealed class GatewayRawCapTests : IDisposable try { var (values, pages, status) = DrainFrom(nm, nodeId, At(10).AddMilliseconds(500), At(3000).AddMilliseconds(500), 0, null, returnBounds: true); - status.Code.ShouldBe(StatusCodes.Good); + status.ShouldBe(StatusCodes.Good); values.ShouldBe(Enumerable.Range(10, 2992).Select(i => (double)i)); // start bound +10, data +11..+3000, end bound +3001 pages.ShouldAllBe(p => p <= Cap); fake.RawCalls.ShouldAllBe(c => c.MaxValues > 0 && c.MaxValues <= Cap + RawAggregateReader.PreWindowAllowance); @@ -277,21 +277,24 @@ public sealed class GatewayRawCapTests : IDisposable private static (IReadOnlyList Values, ServiceResult Error, byte[]? Cp) ReadRaw( OtOpcUaNodeManager nm, NodeId nodeId, DateTime start, DateTime end, uint max, byte[]? inboundCp, bool returnBounds = false) { - var context = new OperationContext(new RequestHeader(), secureChannelContext: null, RequestType.HistoryRead, identity: null); + var context = new OperationContext(new RequestHeader(), secureChannelContext: null, RequestType.HistoryRead, requestLifetime: RequestLifetime.None, identity: null); var details = new ReadRawModifiedDetails { ReturnBounds = returnBounds, IsReadModified = false, StartTime = start, EndTime = end, NumValuesPerNode = max, }; - var nodesToRead = new List { new() { NodeId = nodeId, ContinuationPoint = inboundCp } }; + var nodesToRead = new List { new() { NodeId = nodeId, ContinuationPoint = inboundCp is null ? default : ByteString.From(inboundCp) } }; var results = new List { null! }; var errors = new List { null! }; nm.HistoryRead(context, details, TimestampsToReturn.Both, releaseContinuationPoints: false, nodesToRead, results, errors); var values = new List(); - if (results[0]?.HistoryData is { } ho && !ExtensionObject.IsNull(ho)) - foreach (var dv in ((HistoryData)ExtensionObject.ToEncodeable(ho)).DataValues) - values.Add(Convert.ToDouble(dv.Value)); - return (values, errors[0], results[0]?.ContinuationPoint); + if (results[0]?.HistoryData is { IsNull: false } historyData) + { + var data = (HistoryData)ExtensionObject.ToEncodeable(historyData)!; + foreach (var dv in data.DataValues) + values.Add(Convert.ToDouble(SdkValueBoundary.ToClr(dv.WrappedValue))); + } + return (values, errors[0], results[0]?.ContinuationPoint is { IsNull: false } cp ? cp.ToArray() : null); } public void Dispose() diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/NativeAlarmRestatementEndToEndTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/NativeAlarmRestatementEndToEndTests.cs index bcd4faf8..b611ac6b 100644 --- a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/NativeAlarmRestatementEndToEndTests.cs +++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/NativeAlarmRestatementEndToEndTests.cs @@ -28,7 +28,6 @@ using LocalizedText = Opc.Ua.LocalizedText; using Proto = ZB.MOM.WW.MxGateway.Contracts.Proto; using UaNodeId = Opc.Ua.NodeId; using Variant = Opc.Ua.Variant; -using VariantCollection = Opc.Ua.VariantCollection; namespace ZB.MOM.WW.OtOpcUa.Runtime.Tests.Drivers; @@ -505,9 +504,9 @@ public sealed class NativeAlarmRestatementEndToEndTests : RuntimeActorTestBase } /// An upstream A&C condition event, in the driver's select-clause order. - private static VariantCollection ConditionFields(bool active, bool acked) => + private static Variant[] ConditionFields(bool active, bool acked) => [ - new Variant(new byte[] { 1 }), // EventId + new Variant(Opc.Ua.ByteString.From(new byte[] { 1 })), // EventId new Variant(new UaNodeId("TripAlarmType", 3)), // EventType new Variant(UaNodeId.Parse(UpstreamSource)), // SourceNode new Variant(new LocalizedText("tripped")), // Message diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/OpcUa/ServiceLevelEndToEndTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/OpcUa/ServiceLevelEndToEndTests.cs index 303400b6..06def95e 100644 --- a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/OpcUa/ServiceLevelEndToEndTests.cs +++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/OpcUa/ServiceLevelEndToEndTests.cs @@ -35,7 +35,7 @@ public sealed class ServiceLevelEndToEndTests : RuntimeActorTestBase port => new OpcUaApplicationHost( BuildOptions("PrimaryLeader", pkiRoot, port), NullLogger.Instance), - () => new StandardServer(), Ct); + () => new StandardServer(Opc.Ua.DefaultTelemetry.Create(_ => { })), Ct); await using var host = started.Host; var server = started.Server; @@ -58,7 +58,7 @@ public sealed class ServiceLevelEndToEndTests : RuntimeActorTestBase CorrelationId: CorrelationId.NewId())); AwaitAssertion(() => - server.CurrentInstance.ServerObject.ServiceLevel.Value.ShouldBe((byte)240)); + server.CurrentInstance.ServerObject.ServiceLevel.ShouldNotBeNull().Value.ShouldBe((byte)240)); } finally { @@ -77,7 +77,7 @@ public sealed class ServiceLevelEndToEndTests : RuntimeActorTestBase port => new OpcUaApplicationHost( BuildOptions("Secondary", pkiRoot, port), NullLogger.Instance), - () => new StandardServer(), Ct); + () => new StandardServer(Opc.Ua.DefaultTelemetry.Create(_ => { })), Ct); await using var host = started.Host; var server = started.Server; @@ -100,7 +100,7 @@ public sealed class ServiceLevelEndToEndTests : RuntimeActorTestBase CorrelationId: CorrelationId.NewId())); AwaitAssertion(() => - server.CurrentInstance.ServerObject.ServiceLevel.Value.ShouldBe((byte)100)); + server.CurrentInstance.ServerObject.ServiceLevel.ShouldNotBeNull().Value.ShouldBe((byte)100)); } finally {