/* ======================================================================== * Copyright (c) 2005-2025 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using System.Threading.Tasks; using BenchmarkDotNet.Attributes; using NUnit.Framework; using Opc.Ua.Server.TestFramework; using Quickstarts.ReferenceServer; namespace Opc.Ua.Client.TestFramework { public class ClientTestServerQuotas : ClientTestFramework { internal const int MaxByteStringLengthForTest = 4096; public ClientTestServerQuotas() : base(Utils.UriSchemeOpcTcp) { } public ClientTestServerQuotas(string uriScheme = Utils.UriSchemeOpcTcp) : base(uriScheme) { } /// /// Set up a Server and a Client instance. /// [OneTimeSetUp] public override Task OneTimeSetUpAsync() { SupportsExternalServerUrl = true; return base.OneTimeSetUpAsync(); } /// /// Tear down the Server and the Client. /// [OneTimeTearDown] public override Task OneTimeTearDownAsync() { return base.OneTimeTearDownAsync(); } /// /// Test setup. /// [SetUp] public override Task SetUpAsync() { return base.SetUpAsync(); } public override async Task CreateReferenceServerFixtureAsync( bool enableTracing, bool disableActivityLogging, bool securityNone) { // start Ref server ServerFixture = new ServerFixture( t => new ReferenceServer(t), enableTracing, disableActivityLogging) { UriScheme = UriScheme, SecurityNone = securityNone, AutoAccept = true, AllNodeManagers = true, OperationLimits = true }; await ServerFixture.LoadConfigurationAsync(PkiRoot).ConfigureAwait(false); ServerFixture.Config.TransportQuotas!.MaxMessageSize = TransportQuotaMaxMessageSize; ServerFixture.Config.TransportQuotas.MaxByteStringLength = MaxByteStringLengthForTest; ServerFixture.Config.TransportQuotas.MaxStringLength = TransportQuotaMaxStringLength; ServerFixture.Config.ServerConfiguration!.UserTokenPolicies += new UserTokenPolicy(UserTokenType.UserName); ServerFixture.Config.ServerConfiguration.UserTokenPolicies += new UserTokenPolicy(UserTokenType.Certificate); ServerFixture.Config.ServerConfiguration.UserTokenPolicies += new UserTokenPolicy(UserTokenType.IssuedToken) { IssuedTokenType = Profiles.JwtUserToken }; ReferenceServer = await ServerFixture.StartAsync() .ConfigureAwait(false); ReferenceServer.TokenValidator = TokenValidator; ServerFixturePort = ServerFixture.Port; } /// /// Test teardown. /// [TearDown] public override Task TearDownAsync() { return base.TearDownAsync(); } /// /// Global Setup for benchmarks. /// [GlobalSetup] public override void GlobalSetup() { base.GlobalSetup(); } /// /// Global cleanup for benchmarks. /// [GlobalCleanup] public override void GlobalCleanup() { base.GlobalCleanup(); } [Test] [Order(200)] public async Task TestBoundaryCaseForReadingChunksAsync() { ISession theSession = Session; int namespaceIndex = theSession.NamespaceUris.GetIndex( "http://opcfoundation.org/Quickstarts/ReferenceServer"); var nodeId = NodeId.Parse($"ns={namespaceIndex};s=Scalar_Static_ByteString"); byte[] buffer = new byte[MaxByteStringLengthForTest]; UnsecureRandom.Shared.NextBytes(buffer); var chunk = ByteString.From(buffer); var writeValue = new WriteValue { NodeId = nodeId, AttributeId = Attributes.Value, Value = new DataValue(new Variant(chunk)), IndexRange = null }; ArrayOf writeValues = [writeValue]; WriteResponse result = await theSession.WriteAsync(null, writeValues, default) .ConfigureAwait(false); ArrayOf results = result.Results; if (results[0] != StatusCodes.Good) { Assert.Fail($"Write failed with status code {results[0]}"); } ByteString readData = await theSession.ReadByteStringInChunksAsync(nodeId, default) .ConfigureAwait(false); Assert.That(readData, Is.EqualTo(chunk)); } } }