diff --git a/Tests/Opc.Ua.Client.Tests/ContinuationPointInBatchTest.cs b/Tests/Opc.Ua.Client.Tests/ContinuationPointInBatchTest.cs
index b51e776745..a31fd53998 100644
--- a/Tests/Opc.Ua.Client.Tests/ContinuationPointInBatchTest.cs
+++ b/Tests/Opc.Ua.Client.Tests/ContinuationPointInBatchTest.cs
@@ -114,297 +114,7 @@ protected override void Dispose(bool disposing)
}
};
- public class ServerSessionForTest : Opc.Ua.Server.Session
- {
- public ServerSessionForTest(
- OperationContext context,
- IServerInternal server,
- X509Certificate2 serverCertificate,
- NodeId authenticationToken,
- byte[] clientNonce,
- byte[] serverNonce,
- string sessionName,
- ApplicationDescription
- clientDescription,
- string endpointUrl,
- X509Certificate2 clientCertificate,
- double sessionTimeout,
- uint maxResponseMessageSize,
- double maxRequestAge,
- int maxBrowseContinuationPoints,
- int maxHistoryContinuationPoints
- ) : base(
- context,
- server,
- serverCertificate,
- authenticationToken,
- clientNonce,
- serverNonce,
- sessionName,
- clientDescription,
- endpointUrl,
- clientCertificate,
- sessionTimeout,
- maxResponseMessageSize,
- maxRequestAge,
- maxBrowseContinuationPoints,
- maxHistoryContinuationPoints
- )
- {
- }
-
- public void SetMaxNumberOfContinuationPoints(uint maxNumberOfContinuationPoints)
- {
- MaxBrowseContinuationPoints = (int)maxNumberOfContinuationPoints;
- }
- }
- public class SessionManagerForTest : Opc.Ua.Server.SessionManager
- {
- private IServerInternal m_4TestServer;
- private int m_4TestMaxRequestAge;
- private int m_4TestMaxBrowseContinuationPoints;
- private int m_4TestMaxHistoryContinuationPoints;
- public SessionManagerForTest(IServerInternal server, ApplicationConfiguration configuration) : base(server, configuration)
- {
- m_4TestServer = server;
- m_4TestMaxRequestAge = configuration.ServerConfiguration.MaxRequestAge;
- m_4TestMaxBrowseContinuationPoints = configuration.ServerConfiguration.MaxBrowseContinuationPoints;
- m_4TestMaxHistoryContinuationPoints = configuration.ServerConfiguration.MaxHistoryContinuationPoints;
- }
-
- protected override Opc.Ua.Server.Session CreateSession(
- OperationContext context,
- IServerInternal server,
- X509Certificate2 serverCertificate,
- NodeId sessionCookie,
- byte[] clientNonce,
- byte[] serverNonce,
- string sessionName,
- ApplicationDescription clientDescription,
- string endpointUrl,
- X509Certificate2 clientCertificate,
- double sessionTimeout,
- uint maxResponseMessageSize,
- int maxRequestAge, // TBD - Remove unused parameter.
- int maxContinuationPoints) // TBD - Remove unused parameter.
- {
- ServerSessionForTest session = new ServerSessionForTest(
- context,
- m_4TestServer,
- serverCertificate,
- sessionCookie,
- clientNonce,
- serverNonce,
- sessionName,
- clientDescription,
- endpointUrl,
- clientCertificate,
- sessionTimeout,
- maxResponseMessageSize,
- m_4TestMaxRequestAge,
- m_4TestMaxBrowseContinuationPoints,
- m_4TestMaxHistoryContinuationPoints);
-
- return (Opc.Ua.Server.Session)session;
- }
- }
-
- public class MasterNodeManagerForThisUnitTest : MasterNodeManager
- {
- public MasterNodeManagerForThisUnitTest(IServerInternal server, ApplicationConfiguration configuration, string dynamicNamespaceUri, params INodeManager[] additionalManagers) : base(server, configuration, dynamicNamespaceUri, additionalManagers)
- {
- }
-
- private uint m_maxContinuationPointsPerBrowseForUnitTest = 0;
- public uint MaxContinuationPointsPerBrowseForUnitTest { get => m_maxContinuationPointsPerBrowseForUnitTest; set => m_maxContinuationPointsPerBrowseForUnitTest = value; }
-
- ///
- /// Returns the set of references that meet the filter criteria.
- ///
- public override void Browse(
- OperationContext context,
- ViewDescription view,
- uint maxReferencesPerNode,
- BrowseDescriptionCollection nodesToBrowse,
- out BrowseResultCollection results,
- out DiagnosticInfoCollection diagnosticInfos)
- {
- if (context == null) throw new ArgumentNullException(nameof(context));
- if (nodesToBrowse == null) throw new ArgumentNullException(nameof(nodesToBrowse));
-
- if (view != null && !NodeId.IsNull(view.ViewId))
- {
- INodeManager viewManager = null;
- object viewHandle = GetManagerHandle(view.ViewId, out viewManager);
-
- if (viewHandle == null)
- {
- throw new ServiceResultException(StatusCodes.BadViewIdUnknown);
- }
-
- NodeMetadata metadata = viewManager.GetNodeMetadata(context, viewHandle, BrowseResultMask.NodeClass);
-
- if (metadata == null || metadata.NodeClass != NodeClass.View)
- {
- throw new ServiceResultException(StatusCodes.BadViewIdUnknown);
- }
-
- // validate access rights and role permissions
- ServiceResult validationResult = ValidatePermissions(context, viewManager, viewHandle, PermissionType.Browse, null, true);
- if (ServiceResult.IsBad(validationResult))
- {
- throw new ServiceResultException(validationResult);
- }
- view.Handle = viewHandle;
- }
-
- bool diagnosticsExist = false;
- results = new BrowseResultCollection(nodesToBrowse.Count);
- diagnosticInfos = new DiagnosticInfoCollection(nodesToBrowse.Count);
-
- uint continuationPointsAssigned = 0;
-
- for (int ii = 0; ii < nodesToBrowse.Count; ii++)
- {
- // check if request has timed out or been cancelled.
- if (StatusCode.IsBad(context.OperationStatus))
- {
- // release all allocated continuation points.
- foreach (BrowseResult current in results)
- {
- if (current != null && current.ContinuationPoint != null && current.ContinuationPoint.Length > 0)
- {
- ContinuationPoint cp = context.Session.RestoreContinuationPoint(current.ContinuationPoint);
- cp.Dispose();
- }
- }
-
- throw new ServiceResultException(context.OperationStatus);
- }
-
- BrowseDescription nodeToBrowse = nodesToBrowse[ii];
-
- // initialize result.
- BrowseResult result = new BrowseResult();
- result.StatusCode = StatusCodes.Good;
- results.Add(result);
-
- ServiceResult error = null;
-
- // need to trap unexpected exceptions to handle bugs in the node managers.
- try
- {
- error = base.Browse(
- context,
- view,
- maxReferencesPerNode,
- m_maxContinuationPointsPerBrowseForUnitTest > 0 ?
- continuationPointsAssigned < m_maxContinuationPointsPerBrowseForUnitTest : true,
- nodeToBrowse,
- result);
- }
- catch (Exception e)
- {
- error = ServiceResult.Create(e, StatusCodes.BadUnexpectedError, "Unexpected error browsing node.");
- }
-
- // check for continuation point.
- if (result.ContinuationPoint != null && result.ContinuationPoint.Length > 0)
- {
- continuationPointsAssigned++;
- }
-
- // check for error.
- result.StatusCode = error.StatusCode;
-
- if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0)
- {
- DiagnosticInfo diagnosticInfo = null;
-
- if (error != null && error.Code != StatusCodes.Good)
- {
- diagnosticInfo = ServerUtils.CreateDiagnosticInfo(Server, context, error);
- diagnosticsExist = true;
- }
-
- diagnosticInfos.Add(diagnosticInfo);
- }
- }
-
- // clear the diagnostics array if no diagnostics requested or no errors occurred.
- UpdateDiagnostics(context, diagnosticsExist, ref diagnosticInfos);
- }
-
-
- }
-
- public class ReferenceServerForThisUnitTest : ReferenceServer
- {
- public uint Test_MaxBrowseReferencesPerNode { get; set; } = 10u;
- private MasterNodeManager MasterNodeManagerReference { get; set; }
- private SessionManagerForTest SessionManagerForTest { get; set; }
-
- public override ResponseHeader Browse(
- RequestHeader requestHeader,
- ViewDescription view,
- uint requestedMaxReferencesPerNode,
- BrowseDescriptionCollection nodesToBrowse,
- out BrowseResultCollection results,
- out DiagnosticInfoCollection diagnosticInfos)
- {
- return base.Browse(
- requestHeader,
- view,
- Test_MaxBrowseReferencesPerNode,
- nodesToBrowse,
- out results,
- out diagnosticInfos
- );
-
- }
-
- public void SetMaxNumberOfContinuationPoints(uint maxNumberOfContinuationPoints)
- {
- Configuration.ServerConfiguration.MaxBrowseContinuationPoints = (int)maxNumberOfContinuationPoints;
- ((MasterNodeManagerForThisUnitTest)MasterNodeManagerReference).MaxContinuationPointsPerBrowseForUnitTest = maxNumberOfContinuationPoints;
- List theServerSideSessions = SessionManagerForTest.GetSessions().ToList();
- foreach (Opc.Ua.Server.Session session in theServerSideSessions)
- {
- try
- {
- ((ServerSessionForTest)session).SetMaxNumberOfContinuationPoints(maxNumberOfContinuationPoints);
- }
- catch { }
- }
-
- }
-
- protected override MasterNodeManager CreateMasterNodeManager(IServerInternal server, ApplicationConfiguration configuration)
- {
- Utils.LogInfo(Utils.TraceMasks.StartStop, "Creating the Reference Server Node Manager.");
-
- IList nodeManagers = new List();
-
- // create the custom node manager.
- nodeManagers.Add(new ReferenceNodeManager(server, configuration));
-
- foreach (var nodeManagerFactory in NodeManagerFactories)
- {
- nodeManagers.Add(nodeManagerFactory.Create(server, configuration));
- }
- //this.MasterNodeManagerReference = new MasterNodeManager(server, configuration, null, nodeManagers.ToArray());
- this.MasterNodeManagerReference = new MasterNodeManagerForThisUnitTest(server, configuration, null, nodeManagers.ToArray());
- // create master node manager.
- return this.MasterNodeManagerReference;
- }
-
- protected override SessionManager CreateSessionManager(IServerInternal server, ApplicationConfiguration configuration)
- {
- this.SessionManagerForTest = new SessionManagerForTest(server, configuration);
- return this.SessionManagerForTest;
- }
- }
///
/// Client tests.
@@ -451,8 +161,8 @@ public IEnumerable ManagedBrowseTestDataValues()
};
}
- public ReferenceServerForThisUnitTest ReferenceServerForThisUnitTest { get; set; }
- public ServerFixture ServerFixtureForThisUnitTest { get; set; }
+ public ReferenceServerWithLimits ReferenceServerWithLimits { get; set; }
+ public ServerFixture ServerFixtureWithLimits { get; set; }
public override async Task CreateReferenceServerFixture(
bool enableTracing,
bool disableActivityLogging,
@@ -464,7 +174,7 @@ TextWriter writer
{
// start Ref server
- ServerFixtureForThisUnitTest = new ServerFixture(enableTracing, disableActivityLogging) {
+ ServerFixtureWithLimits = new ServerFixture(enableTracing, disableActivityLogging) {
UriScheme = UriScheme,
SecurityNone = securityNone,
AutoAccept = true,
@@ -475,26 +185,26 @@ TextWriter writer
if (writer != null && enableTracing)
{
- ServerFixtureForThisUnitTest.TraceMasks = Utils.TraceMasks.Error | Utils.TraceMasks.Security;
+ ServerFixtureWithLimits.TraceMasks = Utils.TraceMasks.Error | Utils.TraceMasks.Security;
}
- await ServerFixtureForThisUnitTest.LoadConfiguration(PkiRoot).ConfigureAwait(false);
- ServerFixtureForThisUnitTest.Config.TransportQuotas.MaxMessageSize = TransportQuotaMaxMessageSize;
- ServerFixtureForThisUnitTest.Config.TransportQuotas.MaxByteStringLength =
- ServerFixtureForThisUnitTest.Config.TransportQuotas.MaxStringLength = TransportQuotaMaxStringLength;
+ await ServerFixtureWithLimits.LoadConfiguration(PkiRoot).ConfigureAwait(false);
+ ServerFixtureWithLimits.Config.TransportQuotas.MaxMessageSize = TransportQuotaMaxMessageSize;
+ ServerFixtureWithLimits.Config.TransportQuotas.MaxByteStringLength =
+ ServerFixtureWithLimits.Config.TransportQuotas.MaxStringLength = TransportQuotaMaxStringLength;
- ServerFixtureForThisUnitTest.Config.ServerConfiguration.UserTokenPolicies.Add(new UserTokenPolicy(UserTokenType.UserName));
- ServerFixtureForThisUnitTest.Config.ServerConfiguration.UserTokenPolicies.Add(new UserTokenPolicy(UserTokenType.Certificate));
- ServerFixtureForThisUnitTest.Config.ServerConfiguration.UserTokenPolicies.Add(
+ ServerFixtureWithLimits.Config.ServerConfiguration.UserTokenPolicies.Add(new UserTokenPolicy(UserTokenType.UserName));
+ ServerFixtureWithLimits.Config.ServerConfiguration.UserTokenPolicies.Add(new UserTokenPolicy(UserTokenType.Certificate));
+ ServerFixtureWithLimits.Config.ServerConfiguration.UserTokenPolicies.Add(
new UserTokenPolicy(UserTokenType.IssuedToken) { IssuedTokenType = Opc.Ua.Profiles.JwtUserToken });
- ServerFixtureForThisUnitTest.Config.ServerConfiguration.MaxBrowseContinuationPoints = 2;
- ServerFixtureForThisUnitTest.Config.ServerConfiguration.OperationLimits.MaxNodesPerBrowse = 5;
+ ServerFixtureWithLimits.Config.ServerConfiguration.MaxBrowseContinuationPoints = 2;
+ ServerFixtureWithLimits.Config.ServerConfiguration.OperationLimits.MaxNodesPerBrowse = 5;
- ReferenceServerForThisUnitTest = await ServerFixtureForThisUnitTest.StartAsync(localWriter).ConfigureAwait(false);
- ReferenceServerForThisUnitTest.TokenValidator = this.TokenValidator;
- ReferenceServer = ReferenceServerForThisUnitTest;
- ServerFixturePort = ServerFixtureForThisUnitTest.Port;
+ ReferenceServerWithLimits = await ServerFixtureWithLimits.StartAsync(localWriter).ConfigureAwait(false);
+ ReferenceServerWithLimits.TokenValidator = this.TokenValidator;
+ ReferenceServer = ReferenceServerWithLimits;
+ ServerFixturePort = ServerFixtureWithLimits.Port;
}
public ContinuationPointInBatchTest(string uriScheme = Utils.UriSchemeOpcTcp) :
base(uriScheme)
@@ -656,10 +366,10 @@ public void MBNodeCache_BrowseAllVariables_MultipleNodes(ManagedBrowseTestDataPr
ExpectedNumberOfBadNoCPSCs = testData.ExpectedNumberOfBadNoCPSCs
};
- ReferenceServerForThisUnitTest.Test_MaxBrowseReferencesPerNode =
+ ReferenceServerWithLimits.Test_MaxBrowseReferencesPerNode =
pass1ExpectedResults.InputMaxNumberOfReferencesPerNode;
- ReferenceServerForThisUnitTest.SetMaxNumberOfContinuationPoints(
+ ReferenceServerWithLimits.SetMaxNumberOfContinuationPoints(
pass1ExpectedResults.InputMaxNumberOfContinuationPoints);
theSession.ServerMaxContinuationPointsPerBrowse
= pass1ExpectedResults.InputMaxNumberOfContinuationPoints;
@@ -713,7 +423,7 @@ public void MBNodeCache_BrowseAllVariables_MultipleNodes(ManagedBrowseTestDataPr
/// of allowed browse continuation points the number of results with status code
/// BadNoContinuationPoints is reduced, as well as the number of retry attempts needed
/// to get all browse results.
- /// ii) if the number of allowed browse continuatino points is equal to or greater than
+ /// ii) if the number of allowed browse continuation points is equal to or greater than
/// the number of nodes per browse, there will be no status codes which are bad.
///
/// In all cases, the browse will succeed in the end, and the test verifies that
@@ -724,8 +434,7 @@ public void MBNodeCache_BrowseAllVariables_MultipleNodes(ManagedBrowseTestDataPr
///
/// No return value should have the status code BadContinuationPointInvalid, since there is
/// no attempt to allocate continuation points in parallel from more than one service call.
- ///
- ///
+ ///
[Theory, Order(200)]
public void ManagedBrowseWithManyContinuationPoints(ManagedBrowseTestDataProvider testData)
{
@@ -751,10 +460,10 @@ public void ManagedBrowseWithManyContinuationPoints(ManagedBrowseTestDataProvide
ExpectedNumberOfBadNoCPSCs = new List()
};
- ReferenceServerForThisUnitTest.Test_MaxBrowseReferencesPerNode =
+ ReferenceServerWithLimits.Test_MaxBrowseReferencesPerNode =
pass1ExpectedResults.InputMaxNumberOfReferencesPerNode;
- ReferenceServerForThisUnitTest.SetMaxNumberOfContinuationPoints(
+ ReferenceServerWithLimits.SetMaxNumberOfContinuationPoints(
pass1ExpectedResults.InputMaxNumberOfContinuationPoints);
theSession.ServerMaxContinuationPointsPerBrowse =
pass1ExpectedResults.InputMaxNumberOfContinuationPoints;
@@ -787,10 +496,10 @@ public void ManagedBrowseWithManyContinuationPoints(ManagedBrowseTestDataProvide
// now reset the server qutas to get a browse scenario without continuation points. This allows
// to verify the result from the first browse service call (with quotas in place).
- ReferenceServerForThisUnitTest.Test_MaxBrowseReferencesPerNode =
+ ReferenceServerWithLimits.Test_MaxBrowseReferencesPerNode =
pass2ExpectedResults.InputMaxNumberOfReferencesPerNode;
- ReferenceServerForThisUnitTest.SetMaxNumberOfContinuationPoints(
+ ReferenceServerWithLimits.SetMaxNumberOfContinuationPoints(
pass2ExpectedResults.InputMaxNumberOfContinuationPoints);
theSession.ServerMaxContinuationPointsPerBrowse =
pass2ExpectedResults.InputMaxNumberOfContinuationPoints;
@@ -853,9 +562,8 @@ public void ManagedBrowseWithManyContinuationPoints(ManagedBrowseTestDataProvide
///
/// The server is configured with a certain number of allowed nodes per browse service call
///
- /// The ManagedBrowse method is called with the parameter
- /// executeDefensively set to true, which forces the method to
- /// create packages which have at most
+ /// The ManagedBrowse method is called with the ContinuationPointPolicy 'Balanced'
+ /// which forces the method to create packages which have at most
/// min(maxBrowseContinuationPoints, maxNodesPerBrowse)
/// nodes.
///
@@ -894,10 +602,10 @@ public void BalancedManagedBrowseWithManyContinuationPoints(ManagedBrowseTestDat
ExpectedNumberOfBadNoCPSCs = new List()
};
- ReferenceServerForThisUnitTest.Test_MaxBrowseReferencesPerNode =
+ ReferenceServerWithLimits.Test_MaxBrowseReferencesPerNode =
pass1ExpectedResults.InputMaxNumberOfReferencesPerNode;
- ReferenceServerForThisUnitTest.SetMaxNumberOfContinuationPoints(
+ ReferenceServerWithLimits.SetMaxNumberOfContinuationPoints(
pass1ExpectedResults.InputMaxNumberOfContinuationPoints);
theSession.ServerMaxContinuationPointsPerBrowse
= pass1ExpectedResults.InputMaxNumberOfContinuationPoints;
@@ -930,10 +638,10 @@ public void BalancedManagedBrowseWithManyContinuationPoints(ManagedBrowseTestDat
// now reset the server qutas to get a browse scenario without continuation points. This allows
// to verify the result from the first browse service call (with quotas in place).
- ReferenceServerForThisUnitTest.Test_MaxBrowseReferencesPerNode =
+ ReferenceServerWithLimits.Test_MaxBrowseReferencesPerNode =
pass2ExpectedResults.InputMaxNumberOfReferencesPerNode;
- ReferenceServerForThisUnitTest.SetMaxNumberOfContinuationPoints(
+ ReferenceServerWithLimits.SetMaxNumberOfContinuationPoints(
pass2ExpectedResults.InputMaxNumberOfContinuationPoints);
theSession.ServerMaxContinuationPointsPerBrowse
= pass2ExpectedResults.InputMaxNumberOfContinuationPoints;
@@ -992,8 +700,9 @@ public void BalancedManagedBrowseWithManyContinuationPoints(ManagedBrowseTestDat
///
/// in this test the service result BadContinuationPoint invalid in (an unpredictable subset)
- /// of the return values from the ManagedBrowse method call is enforced, by executing the method
- /// on two sets of nodes both of which require the allocation of BrowseContinuationPoints in the server
+ /// of the return values from the ManagedBrowse method call is enforced, by
+ /// concurrently executing the method on two sets of nodes both of which
+ /// require the allocation of BrowseContinuationPoints in the server
///
/// The following results are expected:
/// on a system which supports parallel execution of threads, at least one of the parallel calls
@@ -1003,7 +712,7 @@ public void BalancedManagedBrowseWithManyContinuationPoints(ManagedBrowseTestDat
/// In the worst case the two calls to ManagedBrowse could end up in an endless loop (to prevent this
/// an upper bound for the number of rebrowse attempts would be needed, or a session wide management
/// of the continuation points the server must potentially allocate for the service calls
- /// from the client.
+ /// from the client).
///
/// The result with regards to the BadNoContinuationPoint should be similar to the one from
/// the ManagedBrowseWithManyContinuationPoints test case
@@ -1035,10 +744,10 @@ public void ParallelManagedBrowseWithManyContinuationPoints(ManagedBrowseTestDat
ExpectedNumberOfBadNoCPSCs = new List()
};
- ReferenceServerForThisUnitTest.Test_MaxBrowseReferencesPerNode =
+ ReferenceServerWithLimits.Test_MaxBrowseReferencesPerNode =
pass1ExpectedResults.InputMaxNumberOfReferencesPerNode;
- ReferenceServerForThisUnitTest.SetMaxNumberOfContinuationPoints(
+ ReferenceServerWithLimits.SetMaxNumberOfContinuationPoints(
pass1ExpectedResults.InputMaxNumberOfContinuationPoints);
theSession.ServerMaxContinuationPointsPerBrowse
= pass1ExpectedResults.InputMaxNumberOfContinuationPoints;
@@ -1080,10 +789,10 @@ public void ParallelManagedBrowseWithManyContinuationPoints(ManagedBrowseTestDat
// finally browse again with a simple browse service call.
// reset server quotas first:
- ReferenceServerForThisUnitTest.Test_MaxBrowseReferencesPerNode =
+ ReferenceServerWithLimits.Test_MaxBrowseReferencesPerNode =
pass2ExpectedResults.InputMaxNumberOfReferencesPerNode;
- ReferenceServerForThisUnitTest.SetMaxNumberOfContinuationPoints(
+ ReferenceServerWithLimits.SetMaxNumberOfContinuationPoints(
pass2ExpectedResults.InputMaxNumberOfContinuationPoints);
theSession.ServerMaxContinuationPointsPerBrowse
= pass2ExpectedResults.InputMaxNumberOfContinuationPoints;
@@ -1146,10 +855,10 @@ public async Task MBNodeCache_BrowseAllVariablesAsync(ManagedBrowseTestDataProvi
ExpectedNumberOfBadNoCPSCs = testData.ExpectedNumberOfBadNoCPSCs
};
- ReferenceServerForThisUnitTest.Test_MaxBrowseReferencesPerNode =
+ ReferenceServerWithLimits.Test_MaxBrowseReferencesPerNode =
pass1ExpectedResults.InputMaxNumberOfReferencesPerNode;
- ReferenceServerForThisUnitTest.SetMaxNumberOfContinuationPoints(
+ ReferenceServerWithLimits.SetMaxNumberOfContinuationPoints(
pass1ExpectedResults.InputMaxNumberOfContinuationPoints);
theSession.ServerMaxContinuationPointsPerBrowse
= pass1ExpectedResults.InputMaxNumberOfContinuationPoints;
@@ -1220,10 +929,10 @@ public async Task MBNodeCache_BrowseAllVariables_MultipleNodesAsync(ManagedBrows
ExpectedNumberOfBadNoCPSCs = testData.ExpectedNumberOfBadNoCPSCs
};
- ReferenceServerForThisUnitTest.Test_MaxBrowseReferencesPerNode =
+ ReferenceServerWithLimits.Test_MaxBrowseReferencesPerNode =
pass1ExpectedResults.InputMaxNumberOfReferencesPerNode;
- ReferenceServerForThisUnitTest.SetMaxNumberOfContinuationPoints(
+ ReferenceServerWithLimits.SetMaxNumberOfContinuationPoints(
pass1ExpectedResults.InputMaxNumberOfContinuationPoints);
theSession.ServerMaxContinuationPointsPerBrowse
= pass1ExpectedResults.InputMaxNumberOfContinuationPoints;
@@ -1268,6 +977,13 @@ public async Task MBNodeCache_BrowseAllVariables_MultipleNodesAsync(ManagedBrows
}
+ ///
+ /// same as the ManagedBrowseWithManyContinuationPoints, but
+ /// with the ContinuationPointPolicy set to 'Default'. Instead of calling
+ /// ManagedBrowse, ManagedBrowseAsync is called directly.
+ ///
+ ///
+ ///
[Theory, Order(420)]
public async Task ManagedBrowseWithManyContinuationPointsAsync(ManagedBrowseTestDataProvider testData)
{
@@ -1291,10 +1007,10 @@ public async Task ManagedBrowseWithManyContinuationPointsAsync(ManagedBrowseTest
ExpectedNumberOfBadNoCPSCs = new List()
};
- ReferenceServerForThisUnitTest.Test_MaxBrowseReferencesPerNode =
+ ReferenceServerWithLimits.Test_MaxBrowseReferencesPerNode =
pass1ExpectedResults.InputMaxNumberOfReferencesPerNode;
- ReferenceServerForThisUnitTest.SetMaxNumberOfContinuationPoints(
+ ReferenceServerWithLimits.SetMaxNumberOfContinuationPoints(
pass1ExpectedResults.InputMaxNumberOfContinuationPoints);
theSession.ServerMaxContinuationPointsPerBrowse
= pass1ExpectedResults.InputMaxNumberOfContinuationPoints;
diff --git a/Tests/Opc.Ua.Client.Tests/ReferenceServerWithLimits.cs b/Tests/Opc.Ua.Client.Tests/ReferenceServerWithLimits.cs
new file mode 100644
index 0000000000..789f5a76dc
--- /dev/null
+++ b/Tests/Opc.Ua.Client.Tests/ReferenceServerWithLimits.cs
@@ -0,0 +1,354 @@
+/* ========================================================================
+ * Copyright (c) 2005-2024 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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Security.Cryptography.X509Certificates;
+using Opc.Ua.Server;
+using Quickstarts.ReferenceServer;
+
+namespace Opc.Ua.Client.Tests
+{
+ ///
+ /// Reference Server modification which allows to change the maximum number
+ /// of (browse) continuation points during the execution of a test.
+ /// This makes it easier to compare browse results without any restriction
+ /// with results where the server may allocate only a limited number of
+ /// continuation points.
+ /// To make this work some other classes must be derived and modified, as
+ /// well (see the ServerSessionWithLimits, SessionManagerWithLimits and
+ /// MasterNodeManagerWithLimits classes).
+ ///
+ /// Use with care. This class and especially its dedicated functionality
+ /// should be used for test purposes only.
+ ///
+ public class ReferenceServerWithLimits : ReferenceServer
+ {
+ public uint Test_MaxBrowseReferencesPerNode { get; set; } = 10u;
+ private MasterNodeManager MasterNodeManagerReference { get; set; }
+ private SessionManagerWithLimits SessionManagerForTest { get; set; }
+
+ public override ResponseHeader Browse(
+ RequestHeader requestHeader,
+ ViewDescription view,
+ uint requestedMaxReferencesPerNode,
+ BrowseDescriptionCollection nodesToBrowse,
+ out BrowseResultCollection results,
+ out DiagnosticInfoCollection diagnosticInfos)
+ {
+ return base.Browse(
+ requestHeader,
+ view,
+ Test_MaxBrowseReferencesPerNode,
+ nodesToBrowse,
+ out results,
+ out diagnosticInfos
+ );
+
+ }
+
+ public void SetMaxNumberOfContinuationPoints(uint maxNumberOfContinuationPoints)
+ {
+ Configuration.ServerConfiguration.MaxBrowseContinuationPoints = (int)maxNumberOfContinuationPoints;
+ ((MasterNodeManagerWithLimits)MasterNodeManagerReference).MaxContinuationPointsPerBrowseForUnitTest = maxNumberOfContinuationPoints;
+ List theServerSideSessions = SessionManagerForTest.GetSessions().ToList();
+ foreach (Opc.Ua.Server.Session session in theServerSideSessions)
+ {
+ try
+ {
+ ((ServerSessionWithLimits)session).SetMaxNumberOfContinuationPoints(maxNumberOfContinuationPoints);
+ }
+ catch { }
+ }
+
+ }
+
+ protected override MasterNodeManager CreateMasterNodeManager(IServerInternal server, ApplicationConfiguration configuration)
+ {
+ Utils.LogInfo(Utils.TraceMasks.StartStop, "Creating the Reference Server Node Manager.");
+
+ IList nodeManagers = new List();
+
+ // create the custom node manager.
+ nodeManagers.Add(new ReferenceNodeManager(server, configuration));
+
+ foreach (var nodeManagerFactory in NodeManagerFactories)
+ {
+ nodeManagers.Add(nodeManagerFactory.Create(server, configuration));
+ }
+ //this.MasterNodeManagerReference = new MasterNodeManager(server, configuration, null, nodeManagers.ToArray());
+ this.MasterNodeManagerReference = new MasterNodeManagerWithLimits(server, configuration, null, nodeManagers.ToArray());
+ // create master node manager.
+ return this.MasterNodeManagerReference;
+ }
+
+ protected override SessionManager CreateSessionManager(IServerInternal server, ApplicationConfiguration configuration)
+ {
+ this.SessionManagerForTest = new SessionManagerWithLimits(server, configuration);
+ return this.SessionManagerForTest;
+ }
+ }
+
+ ///
+ /// provide a means to set the maximum number of browse continuation points to
+ /// the (Server) session.
+ ///
+ public class ServerSessionWithLimits : Opc.Ua.Server.Session
+ {
+ public ServerSessionWithLimits(
+ OperationContext context,
+ IServerInternal server,
+ X509Certificate2 serverCertificate,
+ NodeId authenticationToken,
+ byte[] clientNonce,
+ byte[] serverNonce,
+ string sessionName,
+ ApplicationDescription
+ clientDescription,
+ string endpointUrl,
+ X509Certificate2 clientCertificate,
+ double sessionTimeout,
+ uint maxResponseMessageSize,
+ double maxRequestAge,
+ int maxBrowseContinuationPoints,
+ int maxHistoryContinuationPoints
+ ) : base(
+ context,
+ server,
+ serverCertificate,
+ authenticationToken,
+ clientNonce,
+ serverNonce,
+ sessionName,
+ clientDescription,
+ endpointUrl,
+ clientCertificate,
+ sessionTimeout,
+ maxResponseMessageSize,
+ maxRequestAge,
+ maxBrowseContinuationPoints,
+ maxHistoryContinuationPoints
+ )
+ {
+ }
+
+ public void SetMaxNumberOfContinuationPoints(uint maxNumberOfContinuationPoints)
+ {
+ MaxBrowseContinuationPoints = (int)maxNumberOfContinuationPoints;
+ }
+ }
+
+ ///
+ /// ensures that the (Server) session is the derived one for the test.
+ ///
+ public class SessionManagerWithLimits : Opc.Ua.Server.SessionManager
+ {
+ private IServerInternal m_4TestServer;
+ private int m_4TestMaxRequestAge;
+ private int m_4TestMaxBrowseContinuationPoints;
+ private int m_4TestMaxHistoryContinuationPoints;
+ public SessionManagerWithLimits(IServerInternal server, ApplicationConfiguration configuration) : base(server, configuration)
+ {
+ m_4TestServer = server;
+ m_4TestMaxRequestAge = configuration.ServerConfiguration.MaxRequestAge;
+ m_4TestMaxBrowseContinuationPoints = configuration.ServerConfiguration.MaxBrowseContinuationPoints;
+ m_4TestMaxHistoryContinuationPoints = configuration.ServerConfiguration.MaxHistoryContinuationPoints;
+ }
+
+ protected override Opc.Ua.Server.Session CreateSession(
+ OperationContext context,
+ IServerInternal server,
+ X509Certificate2 serverCertificate,
+ NodeId sessionCookie,
+ byte[] clientNonce,
+ byte[] serverNonce,
+ string sessionName,
+ ApplicationDescription clientDescription,
+ string endpointUrl,
+ X509Certificate2 clientCertificate,
+ double sessionTimeout,
+ uint maxResponseMessageSize,
+ int maxRequestAge, // TBD - Remove unused parameter.
+ int maxContinuationPoints) // TBD - Remove unused parameter.
+ {
+ ServerSessionWithLimits session = new ServerSessionWithLimits(
+ context,
+ m_4TestServer,
+ serverCertificate,
+ sessionCookie,
+ clientNonce,
+ serverNonce,
+ sessionName,
+ clientDescription,
+ endpointUrl,
+ clientCertificate,
+ sessionTimeout,
+ maxResponseMessageSize,
+ m_4TestMaxRequestAge,
+ m_4TestMaxBrowseContinuationPoints,
+ m_4TestMaxHistoryContinuationPoints);
+
+ return (Opc.Ua.Server.Session)session;
+ }
+ }
+
+ ///
+ /// Hack which ensures the injected maximum number of browse continuation points
+ /// is really used when the browse service call is executed.
+ ///
+ public class MasterNodeManagerWithLimits : MasterNodeManager
+ {
+ public MasterNodeManagerWithLimits(IServerInternal server, ApplicationConfiguration configuration, string dynamicNamespaceUri, params INodeManager[] additionalManagers) : base(server, configuration, dynamicNamespaceUri, additionalManagers)
+ {
+ }
+
+ private uint m_maxContinuationPointsPerBrowseForUnitTest = 0;
+ public uint MaxContinuationPointsPerBrowseForUnitTest { get => m_maxContinuationPointsPerBrowseForUnitTest; set => m_maxContinuationPointsPerBrowseForUnitTest = value; }
+
+ ///
+ /// Returns the set of references that meet the filter criteria.
+ ///
+ public override void Browse(
+ OperationContext context,
+ ViewDescription view,
+ uint maxReferencesPerNode,
+ BrowseDescriptionCollection nodesToBrowse,
+ out BrowseResultCollection results,
+ out DiagnosticInfoCollection diagnosticInfos)
+ {
+ if (context == null) throw new ArgumentNullException(nameof(context));
+ if (nodesToBrowse == null) throw new ArgumentNullException(nameof(nodesToBrowse));
+
+ if (view != null && !NodeId.IsNull(view.ViewId))
+ {
+ INodeManager viewManager = null;
+ object viewHandle = GetManagerHandle(view.ViewId, out viewManager);
+
+ if (viewHandle == null)
+ {
+ throw new ServiceResultException(StatusCodes.BadViewIdUnknown);
+ }
+
+ NodeMetadata metadata = viewManager.GetNodeMetadata(context, viewHandle, BrowseResultMask.NodeClass);
+
+ if (metadata == null || metadata.NodeClass != NodeClass.View)
+ {
+ throw new ServiceResultException(StatusCodes.BadViewIdUnknown);
+ }
+
+ // validate access rights and role permissions
+ ServiceResult validationResult = ValidatePermissions(context, viewManager, viewHandle, PermissionType.Browse, null, true);
+ if (ServiceResult.IsBad(validationResult))
+ {
+ throw new ServiceResultException(validationResult);
+ }
+ view.Handle = viewHandle;
+ }
+
+ bool diagnosticsExist = false;
+ results = new BrowseResultCollection(nodesToBrowse.Count);
+ diagnosticInfos = new DiagnosticInfoCollection(nodesToBrowse.Count);
+
+ uint continuationPointsAssigned = 0;
+
+ for (int ii = 0; ii < nodesToBrowse.Count; ii++)
+ {
+ // check if request has timed out or been cancelled.
+ if (StatusCode.IsBad(context.OperationStatus))
+ {
+ // release all allocated continuation points.
+ foreach (BrowseResult current in results)
+ {
+ if (current != null && current.ContinuationPoint != null && current.ContinuationPoint.Length > 0)
+ {
+ ContinuationPoint cp = context.Session.RestoreContinuationPoint(current.ContinuationPoint);
+ cp.Dispose();
+ }
+ }
+
+ throw new ServiceResultException(context.OperationStatus);
+ }
+
+ BrowseDescription nodeToBrowse = nodesToBrowse[ii];
+
+ // initialize result.
+ BrowseResult result = new BrowseResult();
+ result.StatusCode = StatusCodes.Good;
+ results.Add(result);
+
+ ServiceResult error = null;
+
+ // need to trap unexpected exceptions to handle bugs in the node managers.
+ try
+ {
+ error = base.Browse(
+ context,
+ view,
+ maxReferencesPerNode,
+ m_maxContinuationPointsPerBrowseForUnitTest > 0 ?
+ continuationPointsAssigned < m_maxContinuationPointsPerBrowseForUnitTest : true,
+ nodeToBrowse,
+ result);
+ }
+ catch (Exception e)
+ {
+ error = ServiceResult.Create(e, StatusCodes.BadUnexpectedError, "Unexpected error browsing node.");
+ }
+
+ // check for continuation point.
+ if (result.ContinuationPoint != null && result.ContinuationPoint.Length > 0)
+ {
+ continuationPointsAssigned++;
+ }
+
+ // check for error.
+ result.StatusCode = error.StatusCode;
+
+ if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0)
+ {
+ DiagnosticInfo diagnosticInfo = null;
+
+ if (error != null && error.Code != StatusCodes.Good)
+ {
+ diagnosticInfo = ServerUtils.CreateDiagnosticInfo(Server, context, error);
+ diagnosticsExist = true;
+ }
+
+ diagnosticInfos.Add(diagnosticInfo);
+ }
+ }
+
+ // clear the diagnostics array if no diagnostics requested or no errors occurred.
+ UpdateDiagnostics(context, diagnosticsExist, ref diagnosticInfos);
+ }
+
+
+ }
+
+}