From 2da58d03604ae90d669b49820d0fc5090c2eb27c Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Mon, 9 Nov 2026 22:47:58 -0500 Subject: [PATCH] build(deps): OPC Foundation SDK 1.5.378.106 -> 1.5.378.182 (lmxopcua#782 interim hop) Behaviour-neutral hop: pin the SDK AggregateManager default to our TreatUncertainAsBad=false (SDK .182 flipped it to true), parity guard now an explicit deliberate-divergence assertion plus a booted-server check; adapt to obsolete FindPredefinedNode(Type)/TraceConfiguration; Microsoft.Extensions. Logging.Abstractions 10.0.7 -> 10.0.8 (SDK floor); stall wire test's late-flush positive control is best-effort (.176 preserves publish queue ordering). Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV --- Directory.Packages.props | 10 +++--- .../AdvertisedAggregateFunctions.cs | 4 +-- .../OpcUaApplicationHost.cs | 1 - .../OtOpcUaSdkServer.cs | 10 ++++++ .../ServerAggregateConfiguration.cs | 8 +++-- .../ZB.MOM.WW.OtOpcUa.OpcUaServer.csproj | 2 +- .../OpcUaClientDriverStallWireTests.cs | 18 +++++++--- ...tOpcUa.OpcUaServer.IntegrationTests.csproj | 2 +- .../NodeManagerHistoryReadTests.cs | 33 ++++++++++++++++--- 9 files changed, 66 insertions(+), 22 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 7483a331..4b820513 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -85,7 +85,7 @@ - + @@ -124,13 +124,13 @@ provider that breaks the "managed only" rule, which is why it is opt-in per instance. --> - + - - - + + + diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/NodeManagerHistoryReadTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/NodeManagerHistoryReadTests.cs index aa83493f..810d2df1 100644 --- a/tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/NodeManagerHistoryReadTests.cs +++ b/tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/NodeManagerHistoryReadTests.cs @@ -361,7 +361,7 @@ public sealed class NodeManagerHistoryReadTests : IDisposable fake.LastAggregate.ShouldBe(HistoryAggregateType.StandardDeviationPopulation); var diagnostics = (CustomNodeManager2)nm.Server.DiagnosticsNodeManager; - var folder = diagnostics.FindPredefinedNode(ObjectIds.HistoryServerCapabilities_AggregateFunctions, null)!; + var folder = diagnostics.FindPredefinedNode(ObjectIds.HistoryServerCapabilities_AggregateFunctions)!; AggregateFunctionMap.ByNodeId.Keys.Count(id => folder.ReferenceExists(ReferenceTypeIds.Organizes, false, id)) .ShouldBe(AggregateFunctionMap.ByNodeId.Count); @@ -447,20 +447,43 @@ public sealed class NodeManagerHistoryReadTests : IDisposable await host.DisposeAsync(); } - /// #677: the server's declared aggregate defaults are the SDK's own server defaults. + /// + /// #677 / #782: our declared aggregate defaults are pinned, and we DELIBERATELY diverge from the SDK on + /// TreatUncertainAsBad (SDK 1.5.378.182 default is true; Part 13 and our evaluators say false). The SDK-default + /// assertions are a tripwire: if a future SDK changes them, this fails and the divergence is re-decided. + /// [Fact] - public void The_server_aggregate_defaults_agree_with_the_SDK_AggregateManager() + public void The_server_aggregate_defaults_deliberately_diverge_from_the_SDK_on_TreatUncertainAsBad() { var sdk = new Opc.Ua.Server.AggregateManager(null!).GetDefaultConfiguration(null); var ours = ServerAggregateConfiguration.Defaults; - ours.TreatUncertainAsBad.ShouldBe(sdk.TreatUncertainAsBad); + ours.TreatUncertainAsBad.ShouldBeFalse(); + ours.PercentDataBad.ShouldBe((byte)100); + ours.PercentDataGood.ShouldBe((byte)100); + ours.UseSlopedExtrapolation.ShouldBeFalse(); + // What we believe the SDK default is (1.5.378.182): TreatUncertainAsBad flipped to true. + sdk.TreatUncertainAsBad.ShouldBeTrue("the SDK default changed - re-decide the deliberate divergence"); ours.PercentDataBad.ShouldBe(sdk.PercentDataBad); ours.PercentDataGood.ShouldBe(sdk.PercentDataGood); ours.UseSlopedExtrapolation.ShouldBe(sdk.UseSlopedExtrapolation); - ServerAggregateConfiguration.IsServable(sdk).ShouldBeTrue(); + ServerAggregateConfiguration.IsServable(ours).ShouldBeTrue(); + ServerAggregateConfiguration.IsServable(sdk).ShouldBeFalse("the SDK default is not what we serve"); ServerAggregateConfiguration.IsServable(null).ShouldBeTrue(); } + /// #782: the booted SDK server's AggregateManager (live AggregateFilter path) runs under OUR defaults. + [Fact] + public async Task The_booted_SDK_AggregateManager_default_is_our_TreatUncertainAsBad_false() + { + var (host, server) = await BootAsync(); + var cfg = server.CurrentInstance.AggregateManager.GetDefaultConfiguration(null); + cfg.TreatUncertainAsBad.ShouldBeFalse(); + cfg.PercentDataBad.ShouldBe(ServerAggregateConfiguration.PercentDataBad); + cfg.PercentDataGood.ShouldBe(ServerAggregateConfiguration.PercentDataGood); + cfg.UseSlopedExtrapolation.ShouldBeFalse(); + await host.DisposeAsync(); + } + /// #285: a Part 13 aggregate beyond the original five (Interpolative) is forwarded to the /// backend as its own member. [Fact]