示例#1
0
        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;
            }
        }