private static void CreateMonitoredItem( IServerTestServices services, RequestHeader requestHeader, uint subscriptionId, NodeId nodeId) { uint queueSize = 5; var itemsToCreate = new MonitoredItemCreateRequestCollection { // add item new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { AttributeId = Attributes.Value, NodeId = nodeId }, MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 1u, SamplingInterval = -1, Filter = null, DiscardOldest = true, QueueSize = queueSize } } }; var response = services.CreateMonitoredItems(requestHeader, subscriptionId, TimestampsToReturn.Neither, itemsToCreate, out MonitoredItemCreateResultCollection itemCreateResults, out DiagnosticInfoCollection diagnosticInfos); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, itemsToCreate); }
private CallMethodRequestCollection ResendDataCall(StatusCode expectedStatus, UInt32Collection subscriptionIds) { // Find the ResendData method var nodesToCall = new CallMethodRequestCollection(); foreach (var subscriptionId in subscriptionIds) { nodesToCall.Add(new CallMethodRequest() { ObjectId = ObjectIds.Server, MethodId = MethodIds.Server_ResendData, InputArguments = new VariantCollection() { new Variant(subscriptionId) } }); } //call ResendData method with subscription ids m_requestHeader.Timestamp = DateTime.UtcNow; var response = m_server.Call(m_requestHeader, nodesToCall, out var results, out var diagnosticInfos); Assert.AreEqual(expectedStatus, results[0].StatusCode.Code); ServerFixtureUtils.ValidateResponse(response); return(nodesToCall); }
/// <summary> /// Start server fixture on random or fixed port. /// </summary> public async Task <T> StartAsync(TextWriter writer, int port = 0) { Random m_random = new Random(); bool retryStartServer = false; int testPort = port; int serverStartRetries = 1; if (port <= 0) { testPort = ServerFixtureUtils.GetNextFreeIPPort(); serverStartRetries = 25; } do { try { await InternalStartServerAsync(writer, testPort).ConfigureAwait(false); } catch (ServiceResultException sre) { if (serverStartRetries <= 0 || sre.StatusCode != StatusCodes.BadNoCommunication) { throw; } serverStartRetries--; testPort = m_random.Next(ServerFixtureUtils.MinTestPort, ServerFixtureUtils.MaxTestPort); retryStartServer = true; } await Task.Delay(m_random.Next(100, 1000)).ConfigureAwait(false); } while (retryStartServer); return(Server); }
/// <summary> /// Worker method to translate the browse path. /// </summary> public static BrowsePathResultCollection TranslateBrowsePathWorker( IServerTestServices services, ReferenceDescriptionCollection referenceDescriptions, RequestHeader requestHeader, OperationLimits operationLimits) { // Browse template var startingNode = Objects.RootFolder; requestHeader.Timestamp = DateTime.UtcNow; // TranslateBrowsePath bool verifyMaxNodesPerBrowse = operationLimits.MaxNodesPerTranslateBrowsePathsToNodeIds > 0; var browsePaths = new BrowsePathCollection( referenceDescriptions.Select(r => new BrowsePath() { RelativePath = new RelativePath(r.BrowseName), StartingNode = startingNode }) ); BrowsePathResultCollection allBrowsePaths = new BrowsePathResultCollection(); while (browsePaths.Any()) { if (verifyMaxNodesPerBrowse && browsePaths.Count > operationLimits.MaxNodesPerTranslateBrowsePathsToNodeIds) { verifyMaxNodesPerBrowse = false; // Test if server responds with BadTooManyOperations var sre = Assert.Throws <ServiceResultException>(() => _ = services.TranslateBrowsePathsToNodeIds(requestHeader, browsePaths, out var results, out var infos)); Assert.AreEqual(StatusCodes.BadTooManyOperations, sre.StatusCode); } var browsePathSnippet = (operationLimits.MaxNodesPerTranslateBrowsePathsToNodeIds > 0) ? browsePaths.Take((int)operationLimits.MaxNodesPerTranslateBrowsePathsToNodeIds).ToArray() : browsePaths; ResponseHeader response = services.TranslateBrowsePathsToNodeIds(requestHeader, browsePathSnippet, out var browsePathResults, out var diagnosticInfos); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, browsePathSnippet); allBrowsePaths.AddRange(browsePathResults); foreach (var result in browsePathResults) { if (result.Targets?.Count > 0) { TestContext.Out.WriteLine("BrowsePath {0}", result.Targets[0].ToString()); } } if (operationLimits.MaxNodesPerTranslateBrowsePathsToNodeIds == 0) { browsePaths.Clear(); } else { browsePaths = browsePaths.Skip((int)operationLimits.MaxNodesPerTranslateBrowsePathsToNodeIds).ToArray(); } } return(allBrowsePaths); }
/// <summary> /// Worker method to test Transfer of subscriptions to new session. /// </summary> public static void TransferSubscriptionTest( IServerTestServices services, RequestHeader requestHeader, UInt32Collection subscriptionIds, bool sendInitialData, bool expectAccessDenied) { Assert.AreEqual(1, subscriptionIds.Count); requestHeader.Timestamp = DateTime.UtcNow; var response = services.TransferSubscriptions(requestHeader, subscriptionIds, sendInitialData, out TransferResultCollection transferResults, out DiagnosticInfoCollection diagnosticInfos); Assert.AreEqual(StatusCodes.Good, response.ServiceResult.Code); Assert.AreEqual(subscriptionIds.Count, transferResults.Count); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, subscriptionIds); foreach (var transferResult in transferResults) { TestContext.Out.WriteLine("TransferResult: {0}", transferResult.StatusCode); if (expectAccessDenied) { Assert.AreEqual(StatusCodes.BadUserAccessDenied, transferResult.StatusCode.Code); } else { Assert.IsTrue(StatusCode.IsGood(transferResult.StatusCode)); Assert.AreEqual(1, transferResult.AvailableSequenceNumbers.Count); } } if (expectAccessDenied) { return; } requestHeader.Timestamp = DateTime.UtcNow; var acknoledgements = new SubscriptionAcknowledgementCollection(); response = services.Publish(requestHeader, acknoledgements, out uint publishedId, out UInt32Collection availableSequenceNumbers, out bool moreNotifications, out NotificationMessage notificationMessage, out StatusCodeCollection _, out diagnosticInfos); Assert.AreEqual(StatusCodes.Good, response.ServiceResult.Code); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, acknoledgements); Assert.AreEqual(subscriptionIds[0], publishedId); Assert.AreEqual(sendInitialData ? 1 : 0, notificationMessage.NotificationData.Count); //Assert.AreEqual(0, availableSequenceNumbers.Count); requestHeader.Timestamp = DateTime.UtcNow; response = services.DeleteSubscriptions(requestHeader, subscriptionIds, out StatusCodeCollection statusResults, out diagnosticInfos); Assert.AreEqual(StatusCodes.Good, response.ServiceResult.Code); }
/// <summary> /// Read Values of NodeIds, determine types, write back new random values. /// </summary> /// <param name="testSet">The nodeIds to modify.</param> private void UpdateValues(NodeId[] testSet) { // Read values var requestHeader = m_requestHeader; var nodesToRead = new ReadValueIdCollection(); foreach (NodeId nodeId in testSet) { nodesToRead.Add(new ReadValueId() { NodeId = nodeId, AttributeId = Attributes.Value }); } var response = m_server.Read(requestHeader, kMaxAge, TimestampsToReturn.Neither, nodesToRead, out var readDataValues, out var diagnosticInfos); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, readDataValues); Assert.AreEqual(testSet.Length, readDataValues.Count); var modifiedValues = new DataValueCollection(); foreach (var dataValue in readDataValues) { var typeInfo = TypeInfo.Construct(dataValue.Value); Assert.IsNotNull(typeInfo); var value = m_generator.GetRandom(typeInfo.BuiltInType); modifiedValues.Add(new DataValue() { WrappedValue = new Variant(value) }); } int ii = 0; var nodesToWrite = new WriteValueCollection(); foreach (NodeId nodeId in testSet) { nodesToWrite.Add(new WriteValue() { NodeId = nodeId, AttributeId = Attributes.Value, Value = modifiedValues[ii] }); ii++; } // Write Nodes requestHeader.Timestamp = DateTime.UtcNow; response = m_server.Write(requestHeader, nodesToWrite, out var writeDataValues, out diagnosticInfos); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, writeDataValues); }
/// <summary> /// Worker method to test TransferSubscriptions of a server. /// </summary> public static UInt32Collection CreateSubscriptionForTransfer( IServerTestServices services, RequestHeader requestHeader, NodeId[] testNodes, uint queueSize = DefaultMonitoredItemsQueueSize, int samplingInterval = DefaultMonitoredItemsSamplingInterval) { // start time requestHeader.Timestamp = DateTime.UtcNow; uint subscriptionId = CreateSubscription(services, requestHeader); uint clientHandle = 1; foreach (NodeId testNode in testNodes) { CreateMonitoredItem(services, requestHeader, subscriptionId, testNode, clientHandle++, queueSize, samplingInterval); } var subscriptionIds = new UInt32Collection(); subscriptionIds.Add(subscriptionId); // enable publishing var response = services.SetPublishingMode(requestHeader, true, subscriptionIds, out var statuses, out var diagnosticInfos); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, subscriptionIds); // wait some time to settle Thread.Sleep(1000); // publish request var acknoledgements = new SubscriptionAcknowledgementCollection(); response = services.Publish(requestHeader, acknoledgements, out uint publishedId, out UInt32Collection availableSequenceNumbers, out bool moreNotifications, out NotificationMessage notificationMessage, out StatusCodeCollection _, out diagnosticInfos); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, acknoledgements); Assert.AreEqual(subscriptionId, publishedId); // static node, do not acknoledge Assert.AreEqual(1, availableSequenceNumbers.Count); return(subscriptionIds); }
public void Write() { // Write var requestHeader = m_requestHeader; requestHeader.Timestamp = DateTime.UtcNow; var nodesToWrite = new WriteValueCollection(); var nodeId = new NodeId("Scalar_Simulation_Int32", 2); nodesToWrite.Add(new WriteValue() { NodeId = nodeId, AttributeId = Attributes.Value, Value = new DataValue(1234) }); var response = m_server.Write(requestHeader, nodesToWrite, out var dataValues, out var diagnosticInfos); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, dataValues); }
/// <summary> /// Worker method to verify the SubscriptionTransferred message of a server. /// </summary> public static void VerifySubscriptionTransferred( IServerTestServices services, RequestHeader requestHeader, UInt32Collection subscriptionIds, bool deleteSubscriptions) { // start time requestHeader.Timestamp = DateTime.UtcNow; // wait some time to settle Thread.Sleep(100); // publish request var acknoledgements = new SubscriptionAcknowledgementCollection(); var response = services.Publish(requestHeader, acknoledgements, out uint publishedId, out UInt32Collection availableSequenceNumbers, out bool moreNotifications, out NotificationMessage notificationMessage, out StatusCodeCollection _, out var diagnosticInfos); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, acknoledgements); Assert.IsFalse(moreNotifications); Assert.IsTrue(subscriptionIds.Contains(publishedId)); Assert.AreEqual(1, notificationMessage.NotificationData.Count); var statusMessage = notificationMessage.NotificationData[0].ToString(); Assert.IsTrue(statusMessage.Contains("GoodSubscriptionTransferred")); // static node, do not acknoledge if (availableSequenceNumbers != null) { Assert.AreEqual(0, availableSequenceNumbers.Count); } if (deleteSubscriptions) { response = services.DeleteSubscriptions(requestHeader, subscriptionIds, out var _, out diagnosticInfos); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, subscriptionIds); } }
public void ReadAllNodes() { var serverTestServices = new ServerTestServices(m_server); if (m_operationLimits == null) { GetOperationLimits(); } if (m_referenceDescriptions == null) { m_referenceDescriptions = CommonTestWorkers.BrowseFullAddressSpaceWorker(serverTestServices, m_requestHeader, m_operationLimits); } // Read all variables var requestHeader = m_requestHeader; foreach (var reference in m_referenceDescriptions) { requestHeader.Timestamp = DateTime.UtcNow; var nodesToRead = new ReadValueIdCollection(); var nodeId = ExpandedNodeId.ToNodeId(reference.NodeId, m_server.CurrentInstance.NamespaceUris); foreach (var attributeId in ServerFixtureUtils.AttributesIds.Keys) { nodesToRead.Add(new ReadValueId() { NodeId = nodeId, AttributeId = attributeId }); } TestContext.Out.WriteLine("NodeId {0} {1}", reference.NodeId, reference.BrowseName); var response = m_server.Read(requestHeader, MaxAge, TimestampsToReturn.Both, nodesToRead, out var dataValues, out var diagnosticInfos); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, dataValues); foreach (var dataValue in dataValues) { TestContext.Out.WriteLine(" {0}", dataValue.ToString()); } } }
private static uint CreateSubscription(IServerTestServices services, RequestHeader requestHeader) { // start time requestHeader.Timestamp = DateTime.UtcNow; // create subscription double publishingInterval = 1000.0; uint lifetimeCount = 60; uint maxKeepAliveCount = 2; uint maxNotificationPerPublish = 0; byte priority = 128; bool enabled = false; var response = services.CreateSubscription(requestHeader, publishingInterval, lifetimeCount, maxKeepAliveCount, maxNotificationPerPublish, enabled, priority, out uint id, out double revisedPublishingInterval, out uint revisedLifetimeCount, out uint revisedMaxKeepAliveCount); ServerFixtureUtils.ValidateResponse(response); return(id); }
public void Read() { // Read var requestHeader = m_requestHeader; requestHeader.Timestamp = DateTime.UtcNow; var nodesToRead = new ReadValueIdCollection(); var nodeId = new NodeId("Scalar_Simulation_Int32", 2); foreach (var attributeId in ServerFixtureUtils.AttributesIds.Keys) { nodesToRead.Add(new ReadValueId() { NodeId = nodeId, AttributeId = attributeId }); } var response = m_server.Read(requestHeader, MaxAge, TimestampsToReturn.Neither, nodesToRead, out var dataValues, out var diagnosticInfos); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, dataValues); }
public void ResendData(bool updateValues, uint queueSize) { var serverTestServices = new ServerTestServices(m_server); // save old security context, test fixture can only work with one session var securityContext = SecureChannelContext.Current; try { var namespaceUris = m_server.CurrentInstance.NamespaceUris; NodeIdCollection testSetCollection = CommonTestWorkers.NodeIdTestSetStatic.Select(n => ExpandedNodeId.ToNodeId(n, namespaceUris)).ToArray(); testSetCollection.AddRange(CommonTestWorkers.NodeIdTestDataSetStatic.Select(n => ExpandedNodeId.ToNodeId(n, namespaceUris)).ToArray()); NodeId[] testSet = testSetCollection.ToArray(); //Re-use method CreateSubscriptionForTransfer to create a subscription var subscriptionIds = CommonTestWorkers.CreateSubscriptionForTransfer(serverTestServices, m_requestHeader, testSet, queueSize, 0); RequestHeader resendDataRequestHeader = m_server.CreateAndActivateSession("ResendData"); var resendDataSecurityContext = SecureChannelContext.Current; SecureChannelContext.Current = securityContext; // After the ResendData call there will be data to publish again var nodesToCall = ResendDataCall(StatusCodes.Good, subscriptionIds); Thread.Sleep(1000); // Make sure publish queue becomes empty by consuming it Assert.AreEqual(1, subscriptionIds.Count); // Issue a Publish request m_requestHeader.Timestamp = DateTime.UtcNow; var acknoledgements = new SubscriptionAcknowledgementCollection(); var response = serverTestServices.Publish(m_requestHeader, acknoledgements, out uint publishedId, out UInt32Collection availableSequenceNumbers, out bool moreNotifications, out NotificationMessage notificationMessage, out StatusCodeCollection _, out DiagnosticInfoCollection diagnosticInfos); Assert.AreEqual(StatusCodes.Good, response.ServiceResult.Code); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, acknoledgements); Assert.AreEqual(subscriptionIds[0], publishedId); Assert.AreEqual(1, notificationMessage.NotificationData.Count); // Validate nothing to publish a few times const int timesToCallPublish = 3; for (int i = 0; i < timesToCallPublish; i++) { m_requestHeader.Timestamp = DateTime.UtcNow; response = serverTestServices.Publish(m_requestHeader, acknoledgements, out publishedId, out availableSequenceNumbers, out moreNotifications, out notificationMessage, out StatusCodeCollection _, out diagnosticInfos); Assert.AreEqual(StatusCodes.Good, response.ServiceResult.Code); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, acknoledgements); Assert.AreEqual(subscriptionIds[0], publishedId); Assert.AreEqual(0, notificationMessage.NotificationData.Count); } // Validate ResendData method call returns error from different session contexts // call ResendData method from different session context SecureChannelContext.Current = resendDataSecurityContext; resendDataRequestHeader.Timestamp = DateTime.UtcNow; response = m_server.Call(resendDataRequestHeader, nodesToCall, out var results, out diagnosticInfos); SecureChannelContext.Current = securityContext; Assert.AreEqual(StatusCodes.BadUserAccessDenied, results[0].StatusCode.Code); ServerFixtureUtils.ValidateResponse(response); // Still nothing to publish since previous ResendData call did not execute m_requestHeader.Timestamp = DateTime.UtcNow; response = serverTestServices.Publish(m_requestHeader, acknoledgements, out publishedId, out availableSequenceNumbers, out moreNotifications, out notificationMessage, out StatusCodeCollection _, out diagnosticInfos); Assert.AreEqual(StatusCodes.Good, response.ServiceResult.Code); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, acknoledgements); Assert.AreEqual(subscriptionIds[0], publishedId); Assert.AreEqual(0, notificationMessage.NotificationData.Count); if (updateValues) { UpdateValues(testSet); // fill queues, but only a single value per resend publish shall be returned for (int i = 1; i < queueSize; i++) { UpdateValues(testSet); } } // call ResendData method from the same session context ResendDataCall(StatusCodes.Good, subscriptionIds); // Data should be available for publishing now m_requestHeader.Timestamp = DateTime.UtcNow; response = serverTestServices.Publish(m_requestHeader, acknoledgements, out publishedId, out availableSequenceNumbers, out moreNotifications, out notificationMessage, out StatusCodeCollection _, out diagnosticInfos); Assert.AreEqual(StatusCodes.Good, response.ServiceResult.Code); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, acknoledgements); Assert.AreEqual(subscriptionIds[0], publishedId); Assert.AreEqual(1, notificationMessage.NotificationData.Count); var items = notificationMessage.NotificationData.FirstOrDefault(); Assert.IsTrue(items.Body is Opc.Ua.DataChangeNotification); var monitoredItemsCollection = ((Opc.Ua.DataChangeNotification)items.Body).MonitoredItems; Assert.AreEqual(testSet.Length, monitoredItemsCollection.Count); Thread.Sleep(1000); if (updateValues && queueSize > 1) { // remaining queue Data should be sent in this publish m_requestHeader.Timestamp = DateTime.UtcNow; response = serverTestServices.Publish(m_requestHeader, acknoledgements, out publishedId, out availableSequenceNumbers, out moreNotifications, out notificationMessage, out StatusCodeCollection _, out diagnosticInfos); Assert.AreEqual(StatusCodes.Good, response.ServiceResult.Code); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, acknoledgements); Assert.AreEqual(subscriptionIds[0], publishedId); Assert.AreEqual(1, notificationMessage.NotificationData.Count); items = notificationMessage.NotificationData.FirstOrDefault(); Assert.IsTrue(items.Body is Opc.Ua.DataChangeNotification); monitoredItemsCollection = ((Opc.Ua.DataChangeNotification)items.Body).MonitoredItems; Assert.AreEqual(testSet.Length * (queueSize - 1), monitoredItemsCollection.Count, testSet.Length); } // Call ResendData method with invalid subscription Id ResendDataCall(StatusCodes.BadSubscriptionIdInvalid, new UInt32Collection() { subscriptionIds.Last() + 20 }); // Nothing to publish since previous ResendData call did not execute m_requestHeader.Timestamp = DateTime.UtcNow; response = serverTestServices.Publish(m_requestHeader, acknoledgements, out publishedId, out availableSequenceNumbers, out moreNotifications, out notificationMessage, out StatusCodeCollection _, out diagnosticInfos); Assert.AreEqual(StatusCodes.Good, response.ServiceResult.Code); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, acknoledgements); Assert.AreEqual(subscriptionIds[0], publishedId); Assert.AreEqual(0, notificationMessage.NotificationData.Count); resendDataRequestHeader.Timestamp = DateTime.UtcNow; SecureChannelContext.Current = resendDataSecurityContext; m_server.CloseSession(resendDataRequestHeader); } finally { //restore security context, that close connection can work SecureChannelContext.Current = securityContext; } }
/// <summary> /// Worker function to browse the full address space of a server. /// </summary> /// <param name="services">The service interface.</param> /// <param name="operationLimits">The operation limits.</param> public static ReferenceDescriptionCollection BrowseFullAddressSpaceWorker( IServerTestServices services, RequestHeader requestHeader, OperationLimits operationLimits = null, BrowseDescription browseDescription = null) { operationLimits = operationLimits ?? new OperationLimits(); requestHeader.Timestamp = DateTime.UtcNow; // Browse template var startingNode = Objects.RootFolder; var browseTemplate = browseDescription ?? new BrowseDescription { NodeId = startingNode, BrowseDirection = BrowseDirection.Forward, ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences, IncludeSubtypes = true, NodeClassMask = 0, ResultMask = (uint)BrowseResultMask.All }; var browseDescriptionCollection = ServerFixtureUtils.CreateBrowseDescriptionCollectionFromNodeId( new NodeIdCollection(new NodeId[] { Objects.RootFolder }), browseTemplate); // Browse ResponseHeader response = null; uint requestedMaxReferencesPerNode = operationLimits.MaxNodesPerBrowse; bool verifyMaxNodesPerBrowse = operationLimits.MaxNodesPerBrowse > 0; var referenceDescriptions = new ReferenceDescriptionCollection(); // Test if server responds with BadNothingToDo { var sre = Assert.Throws <ServiceResultException>(() => _ = services.Browse(requestHeader, null, 0, browseDescriptionCollection.Take(0).ToArray(), out var results, out var infos)); Assert.AreEqual(StatusCodes.BadNothingToDo, sre.StatusCode); } while (browseDescriptionCollection.Any()) { BrowseResultCollection allResults = new BrowseResultCollection(); if (verifyMaxNodesPerBrowse && browseDescriptionCollection.Count > operationLimits.MaxNodesPerBrowse) { verifyMaxNodesPerBrowse = false; // Test if server responds with BadTooManyOperations var sre = Assert.Throws <ServiceResultException>(() => _ = services.Browse(requestHeader, null, 0, browseDescriptionCollection, out var results, out var infos)); Assert.AreEqual(StatusCodes.BadTooManyOperations, sre.StatusCode); // Test if server responds with BadTooManyOperations var tempBrowsePath = browseDescriptionCollection.Take((int)operationLimits.MaxNodesPerBrowse + 1).ToArray(); sre = Assert.Throws <ServiceResultException>(() => _ = services.Browse(requestHeader, null, 0, tempBrowsePath, out var results, out var infos)); Assert.AreEqual(StatusCodes.BadTooManyOperations, sre.StatusCode); } bool repeatBrowse; var maxNodesPerBrowse = operationLimits.MaxNodesPerBrowse; BrowseResultCollection browseResultCollection = new BrowseResultCollection(); DiagnosticInfoCollection diagnosticsInfoCollection; do { var browseCollection = (maxNodesPerBrowse == 0) ? browseDescriptionCollection : browseDescriptionCollection.Take((int)maxNodesPerBrowse).ToArray(); repeatBrowse = false; try { requestHeader.Timestamp = DateTime.UtcNow; response = services.Browse(requestHeader, null, requestedMaxReferencesPerNode, browseCollection, out browseResultCollection, out diagnosticsInfoCollection); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticsInfoCollection, browseCollection); allResults.AddRange(browseResultCollection); } catch (ServiceResultException sre) { if (sre.StatusCode == StatusCodes.BadEncodingLimitsExceeded || sre.StatusCode == StatusCodes.BadResponseTooLarge) { // try to address by overriding operation limit maxNodesPerBrowse = maxNodesPerBrowse == 0 ? (uint)browseCollection.Count / 2 : maxNodesPerBrowse / 2; repeatBrowse = true; } else { throw; } } } while (repeatBrowse); if (maxNodesPerBrowse == 0) { browseDescriptionCollection.Clear(); } else { browseDescriptionCollection = browseDescriptionCollection.Skip((int)maxNodesPerBrowse).ToArray(); } // Browse next var continuationPoints = ServerFixtureUtils.PrepareBrowseNext(browseResultCollection); while (continuationPoints.Any()) { requestHeader.Timestamp = DateTime.UtcNow; response = services.BrowseNext(requestHeader, false, continuationPoints, out var browseNextResultCollection, out diagnosticsInfoCollection); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticsInfoCollection, continuationPoints); allResults.AddRange(browseNextResultCollection); continuationPoints = ServerFixtureUtils.PrepareBrowseNext(browseNextResultCollection); } // Build browse request for next level var browseTable = new NodeIdCollection(); foreach (var result in allResults) { referenceDescriptions.AddRange(result.References); foreach (var reference in result.References) { browseTable.Add(ExpandedNodeId.ToNodeId(reference.NodeId, null)); } } browseDescriptionCollection = ServerFixtureUtils.CreateBrowseDescriptionCollectionFromNodeId(browseTable, browseTemplate); } referenceDescriptions.Sort((x, y) => (x.NodeId.CompareTo(y.NodeId))); TestContext.Out.WriteLine("Found {0} references on server.", referenceDescriptions.Count); foreach (var reference in referenceDescriptions) { TestContext.Out.WriteLine("NodeId {0} {1} {2}", reference.NodeId, reference.NodeClass, reference.BrowseName); } return(referenceDescriptions); }
public void ResendData() { var serverTestServices = new ServerTestServices(m_server); // save old security context, test fixture can only work with one session var securityContext = SecureChannelContext.Current; try { var namespaceUris = m_server.CurrentInstance.NamespaceUris; NodeId[] testSet = CommonTestWorkers.NodeIdTestSetStatic.Select(n => ExpandedNodeId.ToNodeId(n, namespaceUris)).ToArray(); //Re-use method CreateSubscriptionForTransfer to create a subscription CommonTestWorkers.CreateSubscriptionForTransfer(serverTestServices, m_requestHeader, testSet, out var subscriptionIds); RequestHeader resendDataRequestHeader = m_server.CreateAndActivateSession("ResendData"); var resendDataSecurityContext = SecureChannelContext.Current; // After the ResendData call there will be data to publish again MethodState methodStateInstance = (MethodState)m_server.CurrentInstance. DiagnosticsNodeManager.FindPredefinedNode(MethodIds.Server_ResendData, typeof(MethodState)); var nodesToCall = new CallMethodRequestCollection(); nodesToCall.Add(new CallMethodRequest() { ObjectId = ObjectIds.Server, MethodId = MethodIds.Server_ResendData, InputArguments = new VariantCollection() { new Variant(subscriptionIds.Last()) } }); //call ResendData method from the same session context m_requestHeader.Timestamp = DateTime.UtcNow; var response = m_server.Call(m_requestHeader, nodesToCall, out var results, out var diagnosticInfos); Assert.IsTrue(StatusCode.IsGood(results[0].StatusCode)); ServerFixtureUtils.ValidateResponse(response); Thread.Sleep(1000); // Make sure publish queue becomes empty by consuming it Assert.AreEqual(1, subscriptionIds.Count); // Issue a Publish request m_requestHeader.Timestamp = DateTime.UtcNow; var acknoledgements = new SubscriptionAcknowledgementCollection(); response = serverTestServices.Publish(m_requestHeader, acknoledgements, out uint publishedId, out UInt32Collection availableSequenceNumbers, out bool moreNotifications, out NotificationMessage notificationMessage, out StatusCodeCollection _, out diagnosticInfos); Assert.AreEqual(StatusCodes.Good, response.ServiceResult.Code); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, acknoledgements); Assert.AreEqual(subscriptionIds[0], publishedId); Assert.AreEqual(1, notificationMessage.NotificationData.Count); // Validate nothing to publish a few times const int timesToCallPublish = 3; for (int i = 0; i < timesToCallPublish; i++) { m_requestHeader.Timestamp = DateTime.UtcNow; response = serverTestServices.Publish(m_requestHeader, acknoledgements, out publishedId, out availableSequenceNumbers, out moreNotifications, out notificationMessage, out StatusCodeCollection _, out diagnosticInfos); Assert.AreEqual(StatusCodes.Good, response.ServiceResult.Code); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, acknoledgements); Assert.AreEqual(subscriptionIds[0], publishedId); Assert.AreEqual(0, notificationMessage.NotificationData.Count); } // Validate ResendData method call from same and different session contexts // call ResendData method from different session context resendDataRequestHeader.Timestamp = DateTime.UtcNow; response = m_server.Call(resendDataRequestHeader, nodesToCall, out results, out diagnosticInfos); Assert.AreEqual(StatusCodes.BadUserAccessDenied, results[0].StatusCode.Code); ServerFixtureUtils.ValidateResponse(response); // Still nothing to publish since previous ResendData call did not execute m_requestHeader.Timestamp = DateTime.UtcNow; response = serverTestServices.Publish(m_requestHeader, acknoledgements, out publishedId, out availableSequenceNumbers, out moreNotifications, out notificationMessage, out StatusCodeCollection _, out diagnosticInfos); Assert.AreEqual(StatusCodes.Good, response.ServiceResult.Code); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, acknoledgements); Assert.AreEqual(subscriptionIds[0], publishedId); Assert.AreEqual(0, notificationMessage.NotificationData.Count); //call ResendData method from the same session context m_requestHeader.Timestamp = DateTime.UtcNow; response = m_server.Call(m_requestHeader, nodesToCall, out results, out diagnosticInfos); Assert.IsTrue(StatusCode.IsGood(results[0].StatusCode)); ServerFixtureUtils.ValidateResponse(response); // Data should be available for publishing now m_requestHeader.Timestamp = DateTime.UtcNow; response = serverTestServices.Publish(m_requestHeader, acknoledgements, out publishedId, out availableSequenceNumbers, out moreNotifications, out notificationMessage, out StatusCodeCollection _, out diagnosticInfos); Assert.AreEqual(StatusCodes.Good, response.ServiceResult.Code); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, acknoledgements); Assert.AreEqual(subscriptionIds[0], publishedId); Assert.AreEqual(1, notificationMessage.NotificationData.Count); // Call ResendData method with invalid subscription Id nodesToCall = new CallMethodRequestCollection(); nodesToCall.Add(new CallMethodRequest() { ObjectId = ObjectIds.Server, MethodId = MethodIds.Server_ResendData, InputArguments = new VariantCollection() { new Variant(subscriptionIds.Last() + 20) } }); m_requestHeader.Timestamp = DateTime.UtcNow; response = m_server.Call(m_requestHeader, nodesToCall, out results, out diagnosticInfos); Assert.AreEqual(StatusCodes.BadSubscriptionIdInvalid, results[0].StatusCode.Code); ServerFixtureUtils.ValidateResponse(response); // Nothing to publish since previous ResendData call did not execute m_requestHeader.Timestamp = DateTime.UtcNow; response = serverTestServices.Publish(m_requestHeader, acknoledgements, out publishedId, out availableSequenceNumbers, out moreNotifications, out notificationMessage, out StatusCodeCollection _, out diagnosticInfos); Assert.AreEqual(StatusCodes.Good, response.ServiceResult.Code); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, acknoledgements); Assert.AreEqual(subscriptionIds[0], publishedId); Assert.AreEqual(0, notificationMessage.NotificationData.Count); resendDataRequestHeader.Timestamp = DateTime.UtcNow; SecureChannelContext.Current = resendDataSecurityContext; m_server.CloseSession(resendDataRequestHeader); } finally { //restore security context, that close connection can work SecureChannelContext.Current = securityContext; } }
public void GetOperationLimits() { var readIdCollection = new ReadValueIdCollection() { new ReadValueId() { AttributeId = Attributes.Value, NodeId = VariableIds.Server_ServerCapabilities_OperationLimits_MaxNodesPerRead }, new ReadValueId() { AttributeId = Attributes.Value, NodeId = VariableIds.Server_ServerCapabilities_OperationLimits_MaxNodesPerHistoryReadData }, new ReadValueId() { AttributeId = Attributes.Value, NodeId = VariableIds.Server_ServerCapabilities_OperationLimits_MaxNodesPerHistoryReadEvents }, new ReadValueId() { AttributeId = Attributes.Value, NodeId = VariableIds.Server_ServerCapabilities_OperationLimits_MaxNodesPerWrite }, new ReadValueId() { AttributeId = Attributes.Value, NodeId = VariableIds.Server_ServerCapabilities_OperationLimits_MaxNodesPerHistoryUpdateData }, new ReadValueId() { AttributeId = Attributes.Value, NodeId = VariableIds.Server_ServerCapabilities_OperationLimits_MaxNodesPerHistoryUpdateEvents }, new ReadValueId() { AttributeId = Attributes.Value, NodeId = VariableIds.Server_ServerCapabilities_OperationLimits_MaxNodesPerBrowse }, new ReadValueId() { AttributeId = Attributes.Value, NodeId = VariableIds.Server_ServerCapabilities_OperationLimits_MaxMonitoredItemsPerCall }, new ReadValueId() { AttributeId = Attributes.Value, NodeId = VariableIds.Server_ServerCapabilities_OperationLimits_MaxNodesPerNodeManagement }, new ReadValueId() { AttributeId = Attributes.Value, NodeId = VariableIds.Server_ServerCapabilities_OperationLimits_MaxNodesPerRegisterNodes }, new ReadValueId() { AttributeId = Attributes.Value, NodeId = VariableIds.Server_ServerCapabilities_OperationLimits_MaxNodesPerTranslateBrowsePathsToNodeIds }, new ReadValueId() { AttributeId = Attributes.Value, NodeId = VariableIds.Server_ServerCapabilities_OperationLimits_MaxNodesPerMethodCall } }; var requestHeader = m_requestHeader; requestHeader.Timestamp = DateTime.UtcNow; var response = m_server.Read(requestHeader, MaxAge, TimestampsToReturn.Neither, readIdCollection, out var results, out var diagnosticInfos); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, results); Assert.NotNull(results); Assert.AreEqual(readIdCollection.Count, results.Count); m_operationLimits = new OperationLimits() { MaxNodesPerRead = (uint)results[0].Value, MaxNodesPerHistoryReadData = (uint)results[1].Value, MaxNodesPerHistoryReadEvents = (uint)results[2].Value, MaxNodesPerWrite = (uint)results[3].Value, MaxNodesPerHistoryUpdateData = (uint)results[4].Value, MaxNodesPerHistoryUpdateEvents = (uint)results[5].Value, MaxNodesPerBrowse = (uint)results[6].Value, MaxMonitoredItemsPerCall = (uint)results[7].Value, MaxNodesPerNodeManagement = (uint)results[8].Value, MaxNodesPerRegisterNodes = (uint)results[9].Value, MaxNodesPerTranslateBrowsePathsToNodeIds = (uint)results[10].Value, MaxNodesPerMethodCall = (uint)results[11].Value }; }
/// <summary> /// Worker method to test subscriptions of a server. /// </summary> /// <param name="services"></param> /// <param name="requestHeader"></param> public static void SubscriptionTest( IServerTestServices services, RequestHeader requestHeader) { // start time requestHeader.Timestamp = DateTime.UtcNow; // create subscription double publishingInterval = 1000.0; uint lifetimeCount = 60; uint maxKeepAliveCount = 2; uint maxNotificationPerPublish = 0; byte priority = 128; bool enabled = false; uint queueSize = 5; var response = services.CreateSubscription(requestHeader, publishingInterval, lifetimeCount, maxKeepAliveCount, maxNotificationPerPublish, enabled, priority, out uint id, out double revisedPublishingInterval, out uint revisedLifetimeCount, out uint revisedMaxKeepAliveCount); Assert.AreEqual(publishingInterval, revisedPublishingInterval); Assert.AreEqual(lifetimeCount, revisedLifetimeCount); Assert.AreEqual(maxKeepAliveCount, revisedMaxKeepAliveCount); ServerFixtureUtils.ValidateResponse(response); MonitoredItemCreateRequestCollection itemsToCreate = new MonitoredItemCreateRequestCollection(); // check badnothingtodo var sre = Assert.Throws <ServiceResultException>(() => services.CreateMonitoredItems(requestHeader, id, TimestampsToReturn.Neither, itemsToCreate, out MonitoredItemCreateResultCollection mockResults, out DiagnosticInfoCollection mockInfos)); Assert.AreEqual(StatusCodes.BadNothingToDo, sre.StatusCode); // add item uint handleCounter = 1; itemsToCreate.Add(new MonitoredItemCreateRequest() { ItemToMonitor = new ReadValueId() { AttributeId = Attributes.Value, NodeId = VariableIds.Server_ServerStatus_CurrentTime }, MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters() { ClientHandle = ++handleCounter, SamplingInterval = -1, Filter = null, DiscardOldest = true, QueueSize = queueSize } }); response = services.CreateMonitoredItems(requestHeader, id, TimestampsToReturn.Neither, itemsToCreate, out MonitoredItemCreateResultCollection itemCreateResults, out DiagnosticInfoCollection diagnosticInfos); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, itemsToCreate); // modify subscription response = services.ModifySubscription(requestHeader, id, publishingInterval, lifetimeCount, maxKeepAliveCount, maxNotificationPerPublish, priority, out revisedPublishingInterval, out revisedLifetimeCount, out revisedMaxKeepAliveCount); Assert.AreEqual(publishingInterval, revisedPublishingInterval); Assert.AreEqual(lifetimeCount, revisedLifetimeCount); Assert.AreEqual(maxKeepAliveCount, revisedMaxKeepAliveCount); ServerFixtureUtils.ValidateResponse(response); // modify monitored item, just timestamps to return var itemsToModify = new MonitoredItemModifyRequestCollection(); foreach (var itemCreated in itemCreateResults) { itemsToModify.Add( new MonitoredItemModifyRequest() { MonitoredItemId = itemCreated.MonitoredItemId }); } ; response = services.ModifyMonitoredItems(requestHeader, id, TimestampsToReturn.Both, itemsToModify, out MonitoredItemModifyResultCollection modifyResults, out diagnosticInfos); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, itemsToModify); // publish request var acknoledgements = new SubscriptionAcknowledgementCollection(); response = services.Publish(requestHeader, acknoledgements, out uint subscriptionId, out UInt32Collection availableSequenceNumbers, out bool moreNotifications, out NotificationMessage notificationMessage, out StatusCodeCollection statuses, out diagnosticInfos); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, acknoledgements); Assert.AreEqual(id, subscriptionId); Assert.AreEqual(0, availableSequenceNumbers.Count); // enable publishing enabled = true; var subscriptions = new UInt32Collection() { id }; response = services.SetPublishingMode(requestHeader, enabled, subscriptions, out statuses, out diagnosticInfos); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, subscriptions); // wait some time to fill queue int loopCounter = (int)queueSize; Thread.Sleep(loopCounter * 1000); acknoledgements = new SubscriptionAcknowledgementCollection(); do { // get publish responses response = services.Publish(requestHeader, acknoledgements, out subscriptionId, out availableSequenceNumbers, out moreNotifications, out notificationMessage, out statuses, out diagnosticInfos); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, acknoledgements); Assert.AreEqual(id, subscriptionId); var dataChangeNotification = notificationMessage.NotificationData[0].Body as DataChangeNotification; TestContext.Out.WriteLine("Notification: {0} {1} {2}", notificationMessage.SequenceNumber, dataChangeNotification?.MonitoredItems[0].Value.ToString(), notificationMessage.PublishTime); acknoledgements.Clear(); acknoledgements.Add(new SubscriptionAcknowledgement() { SubscriptionId = id, SequenceNumber = notificationMessage.SequenceNumber }); } while (acknoledgements.Count > 0 && --loopCounter > 0); // republish response = services.Republish(requestHeader, subscriptionId, notificationMessage.SequenceNumber, out notificationMessage); ServerFixtureUtils.ValidateResponse(response); // disable publishing enabled = false; response = services.SetPublishingMode(requestHeader, enabled, subscriptions, out statuses, out diagnosticInfos); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, subscriptions); // delete subscription response = services.DeleteSubscriptions(requestHeader, subscriptions, out statuses, out diagnosticInfos); ServerFixtureUtils.ValidateResponse(response); ServerFixtureUtils.ValidateDiagnosticInfos(diagnosticInfos, subscriptions); }