using Opc.Ua; using Opc.Ua.Server; using Shouldly; using Xunit; namespace ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests; /// /// R08:1.1 (#736): the server raw cap (ServerHistorian:MaxRawValuesPerRead) is advertised as /// HistoryServerCapabilities/MaxReturnDataValues (i=11273) through , /// read back the way a client would — through the SDK master node manager — over a real server. /// public sealed class HistoryServerCapabilitiesAdvertisementTests(BoundsServerFixture fx) : IClassFixture { private async Task ReadAdvertisedAsync() { var context = new OperationContext(new RequestHeader(), secureChannelContext: null, RequestType.Read, identity: null); var nodesToRead = new ReadValueIdCollection { new ReadValueId { NodeId = VariableIds.HistoryServerCapabilities_MaxReturnDataValues, AttributeId = Attributes.Value }, }; var (values, _) = await fx.Nm.Server.NodeManager.ReadAsync(context, 0, TimestampsToReturn.Neither, nodesToRead, TestContext.Current.CancellationToken); values.Count.ShouldBe(1); StatusCode.IsGood(values[0].StatusCode).ShouldBeTrue(values[0].StatusCode.ToString()); return (uint)values[0].Value; } [Fact] public async Task The_cap_is_advertised_as_MaxReturnDataValues_and_a_re_sync_overwrites_it() { await fx.Gate.WaitAsync(TestContext.Current.CancellationToken); try { HistoryPaging.AdvertiseMaxReturnDataValues(fx.Nm.Server, 10_000).ShouldBeTrue(); (await ReadAdvertisedAsync()).ShouldBe(10_000u); HistoryPaging.AdvertiseMaxReturnDataValues(fx.Nm.Server, 2_500).ShouldBeTrue(); (await ReadAdvertisedAsync()).ShouldBe(2_500u); // Unbounded (the opt-out) advertises Part 11's "no limit". HistoryPaging.AdvertiseMaxReturnDataValues(fx.Nm.Server, 0).ShouldBeTrue(); (await ReadAdvertisedAsync()).ShouldBe(0u); HistoryPaging.AdvertiseMaxReturnDataValues(fx.Nm.Server, -5).ShouldBeTrue(); (await ReadAdvertisedAsync()).ShouldBe(0u); } finally { HistoryPaging.AdvertiseMaxReturnDataValues(fx.Nm.Server, 0); fx.Gate.Release(); } } [Fact] public void No_server_is_a_quiet_false() { HistoryPaging.AdvertiseMaxReturnDataValues(null, 10_000).ShouldBeFalse(); } }