public async Task UnpublishNodesOnExistingConfiguration(string publishedNodesFile)
        {
            var standaloneCliModelProviderMock = new Mock <IStandaloneCliModelProvider>();
            var agentConfigProviderMock        = new Mock <IAgentConfigProvider>();
            var engineConfigMock         = new Mock <IEngineConfiguration>();
            var clientConfignMock        = new Mock <IClientServicesConfig>();
            var newtonSoftJsonSerializer = new NewtonSoftJsonSerializer();
            var jobSerializer            = new PublisherJobSerializer(newtonSoftJsonSerializer);
            var logger = TraceLogger.Create();
            var publishedNodesJobConverter = new PublishedNodesJobConverter(logger, newtonSoftJsonSerializer,
                                                                            engineConfigMock.Object, clientConfignMock.Object);

            Utils.CopyContent(publishedNodesFile, _tempFile);
            var standaloneCliModel = new StandaloneCliModel {
                PublishedNodesFile       = _tempFile,
                PublishedNodesSchemaFile = "Storage/publishednodesschema.json"
            };

            standaloneCliModelProviderMock.Setup(p => p.StandaloneCliModel).Returns(standaloneCliModel);
            agentConfigProviderMock.Setup(p => p.Config).Returns(new AgentConfigModel());

            var publishedNodesProvider = new PublishedNodesProvider(standaloneCliModelProviderMock.Object, logger);

            var orchestrator = new StandaloneJobOrchestrator(
                publishedNodesJobConverter,
                standaloneCliModelProviderMock.Object,
                agentConfigProviderMock.Object,
                jobSerializer,
                logger,
                publishedNodesProvider,
                newtonSoftJsonSerializer
                );

            string payload = Utils.GetFileContent(publishedNodesFile);
            var    unpublishNodesRequest = newtonSoftJsonSerializer.Deserialize <List <PublishedNodesEntryModel> >(payload);

            foreach (var request in unpublishNodesRequest)
            {
                await FluentActions
                .Invoking(async() => await orchestrator.UnpublishNodesAsync(request).ConfigureAwait(false))
                .Should()
                .NotThrowAsync()
                .ConfigureAwait(false);
            }

            var tasks = new List <Task <JobProcessingInstructionModel> >();

            for (var i = 0; i < 10; i++)
            {
                tasks.Add(orchestrator.GetAvailableJobAsync(i.ToString(), new JobRequestModel()));
            }

            await Task.WhenAll(tasks).ConfigureAwait(false);

            tasks.Count(t => t.Result != null)
            .Should()
            .Be(0);
        }
 /// <summary>
 /// Initializes _standaloneJobOrchestrator.
 /// This method should be called only after content of _tempFile is set.
 /// </summary>
 private void InitStandaloneJobOrchestrator()
 {
     _standaloneJobOrchestrator = new StandaloneJobOrchestrator(
         _publishedNodesJobConverter,
         _standaloneCliModelProviderMock.Object,
         _agentConfigProviderMock.Object,
         _publisherJobSerializer,
         _logger,
         _publishedNodesProvider,
         _newtonSoftJsonSerializer
         );
 }
Beispiel #3
0
        /// <summary>
        /// publish nodes from publishedNodesFile
        /// </summary>
        private async Task <PublisherMethodsController> publishNodeAsync(string publishedNodesFile)
        {
            var standaloneCliModelProviderMock = new Mock <IStandaloneCliModelProvider>();
            var agentConfigProviderMock        = new Mock <IAgentConfigProvider>();
            var identityMock             = new Mock <IIdentity>();
            var newtonSoftJsonSerializer = new NewtonSoftJsonSerializer();
            var jobSerializer            = new PublisherJobSerializer(newtonSoftJsonSerializer);
            var logger            = TraceLogger.Create();
            var engineConfigMock  = new Mock <IEngineConfiguration>();
            var clientConfignMock = new Mock <IClientServicesConfig>();

            var publishedNodesJobConverter = new PublishedNodesJobConverter(logger, newtonSoftJsonSerializer,
                                                                            engineConfigMock.Object, clientConfignMock.Object);

            Utils.CopyContent("Engine/empty_pn.json", _tempFile);
            var standaloneCli = new StandaloneCliModel {
                PublishedNodesFile       = _tempFile,
                PublishedNodesSchemaFile = "Storage/publishednodesschema.json"
            };

            standaloneCliModelProviderMock.Setup(p => p.StandaloneCliModel).Returns(standaloneCli);
            agentConfigProviderMock.Setup(p => p.Config).Returns(new AgentConfigModel());
            var publishedNodesProvider = new PublishedNodesProvider(standaloneCliModelProviderMock.Object, logger);

            var orchestrator = new StandaloneJobOrchestrator(
                publishedNodesJobConverter,
                standaloneCliModelProviderMock.Object,
                agentConfigProviderMock.Object,
                jobSerializer,
                logger,
                publishedNodesProvider,
                newtonSoftJsonSerializer
                );

            var methodsController = new PublisherMethodsController(orchestrator);

            using var publishPayloads = new StreamReader(publishedNodesFile);
            var publishNodesRequest = newtonSoftJsonSerializer.Deserialize <List <PublishNodesEndpointApiModel> >(
                await publishPayloads.ReadToEndAsync().ConfigureAwait(false));

            foreach (var request in publishNodesRequest)
            {
                await FluentActions
                .Invoking(async() => await methodsController.PublishNodesAsync(request).ConfigureAwait(false))
                .Should()
                .NotThrowAsync()
                .ConfigureAwait(false);
            }
            return(methodsController);
        }
        public async Task PublishNodesStressTest()
        {
            var standaloneCliModelProviderMock = new Mock <IStandaloneCliModelProvider>();
            var agentConfigProviderMock        = new Mock <IAgentConfigProvider>();
            var engineConfigMock         = new Mock <IEngineConfiguration>();
            var clientConfignMock        = new Mock <IClientServicesConfig>();
            var newtonSoftJsonSerializer = new NewtonSoftJsonSerializer();
            var jobSerializer            = new PublisherJobSerializer(newtonSoftJsonSerializer);
            var logger = TraceLogger.Create();
            var publishedNodesJobConverter = new PublishedNodesJobConverter(logger, newtonSoftJsonSerializer,
                                                                            engineConfigMock.Object, clientConfignMock.Object);

            using (var fileStream = new FileStream(_tempFile, FileMode.Open, FileAccess.Write)) {
                fileStream.Write(Encoding.UTF8.GetBytes("[]"));
            }

            var standaloneCliModel = new StandaloneCliModel {
                PublishedNodesFile       = _tempFile,
                PublishedNodesSchemaFile = "Storage/publishednodesschema.json"
            };

            standaloneCliModelProviderMock.Setup(p => p.StandaloneCliModel).Returns(standaloneCliModel);
            agentConfigProviderMock.Setup(p => p.Config).Returns(new AgentConfigModel());

            var publishedNodesProvider = new PublishedNodesProvider(standaloneCliModelProviderMock.Object, logger);

            var orchestrator = new StandaloneJobOrchestrator(
                publishedNodesJobConverter,
                standaloneCliModelProviderMock.Object,
                agentConfigProviderMock.Object,
                jobSerializer,
                logger,
                publishedNodesProvider,
                newtonSoftJsonSerializer
                );

            var numberOfEndpoints = 100;
            var numberOfNodes     = 1000;

            var payload = new List <PublishedNodesEntryModel>();

            for (int endpointIndex = 0; endpointIndex < numberOfEndpoints; ++endpointIndex)
            {
                var model = new PublishedNodesEntryModel {
                    EndpointUrl = new Uri($"opc.tcp://server{endpointIndex}:49580"),
                };

                model.OpcNodes = new List <OpcNodeModel>();
                for (var nodeIndex = 0; nodeIndex < numberOfNodes; ++nodeIndex)
                {
                    model.OpcNodes.Add(new OpcNodeModel {
                        Id = $"ns=2;s=Node-Server-{nodeIndex}",
                    });
                }

                payload.Add(model);
            }

            // Publish all nodes.
            foreach (var request in payload)
            {
                await FluentActions
                .Invoking(async() => await orchestrator.PublishNodesAsync(request).ConfigureAwait(false))
                .Should()
                .NotThrowAsync()
                .ConfigureAwait(false);
            }

            async Task CheckEndpointsAndNodes(
                int expectedNumberOfEndpoints,
                int expectedNumberOfNodes
                )
            {
                var tasks = new List <Task <JobProcessingInstructionModel> >();

                for (var i = 0; i < expectedNumberOfEndpoints + 1; i++)
                {
                    tasks.Add(orchestrator.GetAvailableJobAsync(i.ToString(), new JobRequestModel()));
                }

                await Task.WhenAll(tasks).ConfigureAwait(false);

                tasks.Count(t => t.Result != null)
                .Should()
                .Be(expectedNumberOfEndpoints);

                var distinctConfigurations = tasks
                                             .Where(t => t.Result != null)
                                             .Select(t => t.Result.Job.JobConfiguration)
                                             .Distinct();

                distinctConfigurations.Count()
                .Should()
                .Be(expectedNumberOfEndpoints);

                var writerGroups = tasks
                                   .Where(t => t.Result != null)
                                   .Select(t => jobSerializer.DeserializeJobConfiguration(
                                               t.Result.Job.JobConfiguration, t.Result.Job.JobConfigurationType) as WriterGroupJobModel);

                writerGroups.Select(
                    jobModel => jobModel.WriterGroup.DataSetWriters
                    .Select(writer => writer.DataSet.DataSetSource.PublishedVariables.PublishedData.Count())
                    .Sum()
                    ).Count(v => v == expectedNumberOfNodes)
                .Should()
                .Be(expectedNumberOfEndpoints);
            }

            // Check
            await CheckEndpointsAndNodes(numberOfEndpoints, numberOfNodes).ConfigureAwait(false);

            // Publish one more node for each endpoint.
            var payloadDiff = new List <PublishedNodesEntryModel>();

            for (int endpointIndex = 0; endpointIndex < numberOfEndpoints; ++endpointIndex)
            {
                var model = new PublishedNodesEntryModel {
                    EndpointUrl = new Uri($"opc.tcp://server{endpointIndex}:49580"),
                    OpcNodes    = new List <OpcNodeModel> {
                        new OpcNodeModel {
                            Id = $"ns=2;s=Node-Server-{numberOfNodes}",
                        }
                    }
                };

                payloadDiff.Add(model);
            }

            foreach (var request in payloadDiff)
            {
                await FluentActions
                .Invoking(async() => await orchestrator.PublishNodesAsync(request).ConfigureAwait(false))
                .Should()
                .NotThrowAsync()
                .ConfigureAwait(false);
            }

            // Check
            await CheckEndpointsAndNodes(numberOfEndpoints, numberOfNodes + 1).ConfigureAwait(false);

            // Unpublish new nodes for each endpoint.
            foreach (var request in payloadDiff)
            {
                await FluentActions
                .Invoking(async() => await orchestrator.UnpublishNodesAsync(request).ConfigureAwait(false))
                .Should()
                .NotThrowAsync()
                .ConfigureAwait(false);
            }

            // Check
            await CheckEndpointsAndNodes(numberOfEndpoints, numberOfNodes).ConfigureAwait(false);
        }
        public async Task UnpublishNodesOnNonExistingConfiguration(string existingConfig, string newConfig)
        {
            var standaloneCliModelProviderMock = new Mock <IStandaloneCliModelProvider>();
            var agentConfigProviderMock        = new Mock <IAgentConfigProvider>();
            var engineConfigMock         = new Mock <IEngineConfiguration>();
            var clientConfignMock        = new Mock <IClientServicesConfig>();
            var newtonSoftJsonSerializer = new NewtonSoftJsonSerializer();
            var jobSerializer            = new PublisherJobSerializer(newtonSoftJsonSerializer);
            var logger = TraceLogger.Create();
            var publishedNodesJobConverter = new PublishedNodesJobConverter(logger, newtonSoftJsonSerializer,
                                                                            engineConfigMock.Object, clientConfignMock.Object);

            Utils.CopyContent(existingConfig, _tempFile);
            var standaloneCliModel = new StandaloneCliModel {
                PublishedNodesFile       = _tempFile,
                PublishedNodesSchemaFile = "Storage/publishednodesschema.json"
            };

            standaloneCliModelProviderMock.Setup(p => p.StandaloneCliModel).Returns(standaloneCliModel);
            agentConfigProviderMock.Setup(p => p.Config).Returns(new AgentConfigModel());

            var publishedNodesProvider = new PublishedNodesProvider(standaloneCliModelProviderMock.Object, logger);

            var orchestrator = new StandaloneJobOrchestrator(
                publishedNodesJobConverter,
                standaloneCliModelProviderMock.Object,
                agentConfigProviderMock.Object,
                jobSerializer,
                logger,
                publishedNodesProvider,
                newtonSoftJsonSerializer
                );

            string payload = Utils.GetFileContent(newConfig);
            var    unpublishNodesRequest = newtonSoftJsonSerializer.Deserialize <List <PublishedNodesEntryModel> >(payload);

            foreach (var request in unpublishNodesRequest)
            {
                await FluentActions
                .Invoking(async() => await orchestrator.UnpublishNodesAsync(request).ConfigureAwait(false))
                .Should()
                .ThrowAsync <MethodCallStatusException>()
                .WithMessage($"{{\"Message\":\"Response 404 Endpoint not found: {request.EndpointUrl}\",\"Details\":{{}}}}")
                .ConfigureAwait(false);
            }

            var tasks = new List <Task <JobProcessingInstructionModel> >();

            for (var i = 0; i < 10; i++)
            {
                tasks.Add(orchestrator.GetAvailableJobAsync(i.ToString(), new JobRequestModel()));
            }

            await Task.WhenAll(tasks).ConfigureAwait(false);

            tasks.Count(t => t.Result != null)
            .Should()
            .Be(2);

            var distinctConfigurations = tasks
                                         .Where(t => t.Result != null)
                                         .Select(t => t.Result.Job.JobConfiguration)
                                         .Distinct();

            distinctConfigurations.Count()
            .Should()
            .Be(2);
        }
Beispiel #6
0
        public async Task DmApiGetConfiguredEndpointsTest(string publishedNodesFile)
        {
            var standaloneCliModelProviderMock = new Mock <IStandaloneCliModelProvider>();
            var agentConfigProviderMock        = new Mock <IAgentConfigProvider>();
            var identityMock             = new Mock <IIdentity>();
            var newtonSoftJsonSerializer = new NewtonSoftJsonSerializer();
            var jobSerializer            = new PublisherJobSerializer(newtonSoftJsonSerializer);
            var logger            = TraceLogger.Create();
            var engineConfigMock  = new Mock <IEngineConfiguration>();
            var clientConfignMock = new Mock <IClientServicesConfig>();

            var publishedNodesJobConverter = new PublishedNodesJobConverter(logger, newtonSoftJsonSerializer,
                                                                            engineConfigMock.Object, clientConfignMock.Object);

            Utils.CopyContent("Engine/empty_pn.json", _tempFile);
            var standaloneCli = new StandaloneCliModel {
                PublishedNodesFile       = _tempFile,
                PublishedNodesSchemaFile = "Storage/publishednodesschema.json"
            };

            standaloneCliModelProviderMock.Setup(p => p.StandaloneCliModel).Returns(standaloneCli);
            agentConfigProviderMock.Setup(p => p.Config).Returns(new AgentConfigModel());

            var publishedNodesProvider = new PublishedNodesProvider(standaloneCliModelProviderMock.Object, logger);

            var orchestrator = new StandaloneJobOrchestrator(
                publishedNodesJobConverter,
                standaloneCliModelProviderMock.Object,
                agentConfigProviderMock.Object,
                jobSerializer,
                logger,
                publishedNodesProvider,
                newtonSoftJsonSerializer
                );

            var methodsController = new PublisherMethodsController(orchestrator);

            using var publishPayloads = new StreamReader(publishedNodesFile);
            var publishNodesRequests = newtonSoftJsonSerializer.Deserialize <List <PublishNodesEndpointApiModel> >
                                           (await publishPayloads.ReadToEndAsync().ConfigureAwait(false));

            // Check that GetConfiguredEndpointsAsync returns empty list
            var endpoints = await FluentActions
                            .Invoking(async() => await methodsController
                                      .GetConfiguredEndpointsAsync().ConfigureAwait(false))
                            .Should()
                            .NotThrowAsync()
                            .ConfigureAwait(false);

            endpoints.Subject.Endpoints.Count.Should().Be(0);

            // Publish nodes
            foreach (var request in publishNodesRequests)
            {
                await FluentActions
                .Invoking(async() => await methodsController
                          .PublishNodesAsync(request).ConfigureAwait(false))
                .Should()
                .NotThrowAsync()
                .ConfigureAwait(false);
            }

            // Check configured endpoints count
            endpoints = await FluentActions
                        .Invoking(async() => await methodsController
                                  .GetConfiguredEndpointsAsync().ConfigureAwait(false))
                        .Should()
                        .NotThrowAsync()
                        .ConfigureAwait(false);

            endpoints.Subject.Endpoints.Count.Should().Be(5);
            endpoints.Subject.Endpoints[0].Tag.Should().Be("Tag_Leaf0_10000_3085991c-b85c-4311-9bfb-a916da952234");
            endpoints.Subject.Endpoints[1].Tag.Should().Be("Tag_Leaf1_10000_2e4fc28f-ffa2-4532-9f22-378d47bbee5d");
            endpoints.Subject.Endpoints[2].Tag.Should().Be("Tag_Leaf2_10000_3085991c-b85c-4311-9bfb-a916da952234");
            endpoints.Subject.Endpoints[3].Tag.Should().Be("Tag_Leaf3_10000_2e4fc28f-ffa2-4532-9f22-378d47bbee5d");
            endpoints.Subject.Endpoints[4].Tag.Should().BeNull();

            var endpointsHash = endpoints.Subject.Endpoints.Select(e => e.GetHashCode()).ToList();

            Assert.True(endpointsHash.Distinct().Count() == endpointsHash.Count());
        }
Beispiel #7
0
        public async Task DmApiPublishUnpublishNodesTest(string publishedNodesFile)
        {
            var standaloneCliModelProviderMock = new Mock <IStandaloneCliModelProvider>();
            var agentConfigProviderMock        = new Mock <IAgentConfigProvider>();
            var identityMock             = new Mock <IIdentity>();
            var newtonSoftJsonSerializer = new NewtonSoftJsonSerializer();
            var jobSerializer            = new PublisherJobSerializer(newtonSoftJsonSerializer);
            var logger            = TraceLogger.Create();
            var engineConfigMock  = new Mock <IEngineConfiguration>();
            var clientConfignMock = new Mock <IClientServicesConfig>();

            var publishedNodesJobConverter = new PublishedNodesJobConverter(logger, newtonSoftJsonSerializer,
                                                                            engineConfigMock.Object, clientConfignMock.Object);

            Utils.CopyContent("Engine/empty_pn.json", _tempFile);
            var standaloneCli = new StandaloneCliModel {
                PublishedNodesFile       = _tempFile,
                PublishedNodesSchemaFile = "Storage/publishednodesschema.json"
            };

            standaloneCliModelProviderMock.Setup(p => p.StandaloneCliModel).Returns(standaloneCli);
            agentConfigProviderMock.Setup(p => p.Config).Returns(new AgentConfigModel());

            var publishedNodesProvider = new PublishedNodesProvider(standaloneCliModelProviderMock.Object, logger);

            var orchestrator = new StandaloneJobOrchestrator(
                publishedNodesJobConverter,
                standaloneCliModelProviderMock.Object,
                agentConfigProviderMock.Object,
                jobSerializer,
                logger,
                publishedNodesProvider,
                newtonSoftJsonSerializer
                );

            var methodsController = new PublisherMethodsController(orchestrator);

            using var publishPayloads = new StreamReader(publishedNodesFile);
            var publishNodesRequest = newtonSoftJsonSerializer.Deserialize <List <PublishNodesEndpointApiModel> >(
                await publishPayloads.ReadToEndAsync().ConfigureAwait(false));

            foreach (var request in publishNodesRequest)
            {
                var initialNode = request.OpcNodes.First();
                for (int i = 0; i < 10000; i++)
                {
                    request.OpcNodes.Add(new PublishedNodeApiModel {
                        Id                        = initialNode.Id + i.ToString(),
                        DataSetFieldId            = initialNode.DataSetFieldId,
                        DisplayName               = initialNode.DisplayName,
                        ExpandedNodeId            = initialNode.ExpandedNodeId,
                        HeartbeatIntervalTimespan = initialNode.HeartbeatIntervalTimespan,
                        OpcPublishingInterval     = initialNode.OpcPublishingInterval,
                        OpcSamplingInterval       = initialNode.OpcSamplingInterval,
                        QueueSize                 = initialNode.QueueSize,
                        // ToDo: Implement mechanism for SkipFirst.
                        SkipFirst = initialNode.SkipFirst,
                    });
                }

                await FluentActions
                .Invoking(async() => await methodsController.PublishNodesAsync(request).ConfigureAwait(false))
                .Should()
                .NotThrowAsync()
                .ConfigureAwait(false);
            }

            var tasks = new List <Task <JobProcessingInstructionModel> >();

            for (var i = 0; i < 10; i++)
            {
                tasks.Add(orchestrator.GetAvailableJobAsync(i.ToString(), new JobRequestModel()));
            }

            tasks.Where(t => t.Result != null)
            .Select(t => t.Result.Job.JobConfiguration)
            .Distinct().Count()
            .Should()
            .Be(2);

            foreach (var request in publishNodesRequest)
            {
                await FluentActions
                .Invoking(async() => await methodsController
                          .UnpublishNodesAsync(request).ConfigureAwait(false))
                .Should()
                .NotThrowAsync()
                .ConfigureAwait(false);
            }

            tasks = new List <Task <JobProcessingInstructionModel> >();
            for (var i = 0; i < 10; i++)
            {
                tasks.Add(orchestrator.GetAvailableJobAsync(i.ToString(), new JobRequestModel()));
            }

            tasks.Where(t => t.Result != null).Count()
            .Should()
            .Be(0);
        }
Beispiel #8
0
        public async Task DmApiPublishNodesToJobTest(string publishedNodesFile)
        {
            var standaloneCliModelProviderMock = new Mock <IStandaloneCliModelProvider>();
            var agentConfigProviderMock        = new Mock <IAgentConfigProvider>();
            var identityMock             = new Mock <IIdentity>();
            var newtonSoftJsonSerializer = new NewtonSoftJsonSerializer();
            var jobSerializer            = new PublisherJobSerializer(newtonSoftJsonSerializer);
            var logger            = TraceLogger.Create();
            var engineConfigMock  = new Mock <IEngineConfiguration>();
            var clientConfignMock = new Mock <IClientServicesConfig>();

            var publishedNodesJobConverter = new PublishedNodesJobConverter(logger, newtonSoftJsonSerializer,
                                                                            engineConfigMock.Object, clientConfignMock.Object);

            Utils.CopyContent("Engine/empty_pn.json", _tempFile);
            var standaloneCli = new StandaloneCliModel {
                PublishedNodesFile       = _tempFile,
                PublishedNodesSchemaFile = "Storage/publishednodesschema.json"
            };

            standaloneCliModelProviderMock.Setup(p => p.StandaloneCliModel).Returns(standaloneCli);
            agentConfigProviderMock.Setup(p => p.Config).Returns(new AgentConfigModel());

            var publishedNodesProvider = new PublishedNodesProvider(standaloneCliModelProviderMock.Object, logger);

            var orchestrator = new StandaloneJobOrchestrator(
                publishedNodesJobConverter,
                standaloneCliModelProviderMock.Object,
                agentConfigProviderMock.Object,
                jobSerializer,
                logger,
                publishedNodesProvider,
                newtonSoftJsonSerializer
                );

            var methodsController = new PublisherMethodsController(orchestrator);

            using var publishPayloads = new StreamReader(publishedNodesFile);
            var publishNodesRequests = newtonSoftJsonSerializer.Deserialize <List <PublishNodesEndpointApiModel> >
                                           (await publishPayloads.ReadToEndAsync().ConfigureAwait(false));

            foreach (var request in publishNodesRequests)
            {
                await FluentActions
                .Invoking(async() => await methodsController
                          .PublishNodesAsync(request).ConfigureAwait(false))
                .Should()
                .NotThrowAsync()
                .ConfigureAwait(false);
            }

            var tasks = new List <Task <JobProcessingInstructionModel> >();

            for (var i = 0; i < 10; i++)
            {
                tasks.Add(orchestrator.GetAvailableJobAsync(i.ToString(), new JobRequestModel()));
            }

            var job = tasks.Where(t => t.Result != null)
                      .Select(t => t.Result.Job)
                      .Distinct();

            job.Count()
            .Should()
            .Be(2);

            var jobModel = jobSerializer.DeserializeJobConfiguration(
                job.First().JobConfiguration, job.First().JobConfigurationType) as WriterGroupJobModel;

            jobModel.WriterGroup.DataSetWriters.Count.Should().Be(4);
            foreach (var datasetWriter in jobModel.WriterGroup.DataSetWriters)
            {
                datasetWriter.DataSet.DataSetSource.Connection.Endpoint.Url
                .Should()
                .Be(publishNodesRequests.First().EndpointUrl);
                datasetWriter.DataSet.DataSetSource.Connection.Endpoint.SecurityMode
                .Should()
                .Be(publishNodesRequests.First().UseSecurity ? SecurityMode.Best : SecurityMode.None);

                datasetWriter.DataSet.DataSetSource.Connection.User.
                IsSameAs(new CredentialModel {
                    Type = publishNodesRequests.First().OpcAuthenticationMode == AuthenticationMode.Anonymous ?
                           CredentialType.None :
                           CredentialType.UserName,
                    Value = newtonSoftJsonSerializer.FromObject(
                        new {
                        user     = publishNodesRequests.First().UserName,
                        password = publishNodesRequests.First().Password,
                    })
                })
                .Should()
                .BeTrue();
            }
        }
        public async Task Leacy25PublishedNodesFile(string publishedNodesFile)
        {
            Utils.CopyContent(publishedNodesFile, _tempFile);
            InitStandaloneJobOrchestrator();

            var endpoints = await _standaloneJobOrchestrator.GetConfiguredEndpointsAsync().ConfigureAwait(false);

            Assert.Equal(1, endpoints.Count);

            var endpoint = endpoints[0];

            Assert.Equal(endpoint.EndpointUrl, new Uri("opc.tcp://opcplc:50000"));
            Assert.Equal(endpoint.UseSecurity, false);
            Assert.Equal(endpoint.OpcAuthenticationMode, OpcAuthenticationMode.UsernamePassword);
            Assert.Equal(endpoint.OpcAuthenticationUsername, "username");
            Assert.Equal(endpoint.OpcAuthenticationPassword, null);

            endpoint.OpcAuthenticationPassword = "******";

            var nodes = await _standaloneJobOrchestrator.GetConfiguredNodesOnEndpointAsync(endpoint).ConfigureAwait(false);

            Assert.Equal(1, nodes.Count);
            Assert.Equal("nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt1", nodes[0].Id);

            endpoint.OpcNodes = new List <OpcNodeModel>();
            endpoint.OpcNodes.Add(new OpcNodeModel {
                Id = "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt2",
            });

            await _standaloneJobOrchestrator.PublishNodesAsync(endpoint).ConfigureAwait(false);

            endpoints = await _standaloneJobOrchestrator.GetConfiguredEndpointsAsync().ConfigureAwait(false);

            Assert.Equal(1, endpoints.Count);

            endpoint.OpcNodes = null;
            nodes             = await _standaloneJobOrchestrator.GetConfiguredNodesOnEndpointAsync(endpoint).ConfigureAwait(false);

            Assert.Equal(2, nodes.Count);
            Assert.Equal("nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt1", nodes[0].Id);
            Assert.Equal("nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt2", nodes[1].Id);

            // Simulate restart.
            _standaloneJobOrchestrator.Dispose();
            _standaloneJobOrchestrator = null;
            InitStandaloneJobOrchestrator();

            // We should get the same endpoint and nodes after restart.
            endpoints = await _standaloneJobOrchestrator.GetConfiguredEndpointsAsync().ConfigureAwait(false);

            Assert.Equal(1, endpoints.Count);

            endpoint = endpoints[0];
            Assert.Equal(endpoint.EndpointUrl, new Uri("opc.tcp://opcplc:50000"));
            Assert.Equal(endpoint.UseSecurity, false);
            Assert.Equal(endpoint.OpcAuthenticationMode, OpcAuthenticationMode.UsernamePassword);
            Assert.Equal(endpoint.OpcAuthenticationUsername, "username");
            Assert.Equal(endpoint.OpcAuthenticationPassword, null);

            endpoint.OpcAuthenticationPassword = "******";

            nodes = await _standaloneJobOrchestrator.GetConfiguredNodesOnEndpointAsync(endpoint).ConfigureAwait(false);

            Assert.Equal(2, nodes.Count);
            Assert.Equal("nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt1", nodes[0].Id);
            Assert.Equal("nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt2", nodes[1].Id);
        }
        public async Task OptionalFieldsPublishedNodesFile(string publishedNodesFile)
        {
            Utils.CopyContent(publishedNodesFile, _tempFile);
            InitStandaloneJobOrchestrator();

            var endpoints = await _standaloneJobOrchestrator.GetConfiguredEndpointsAsync().ConfigureAwait(false);

            Assert.Equal(2, endpoints.Count);

            Assert.Equal(endpoints[0].DataSetWriterGroup, "Leaf0");
            Assert.Equal(endpoints[0].EndpointUrl, new Uri("opc.tcp://opcplc:50000"));
            Assert.Equal(endpoints[0].UseSecurity, false);
            Assert.Equal(endpoints[0].OpcAuthenticationMode, OpcAuthenticationMode.Anonymous);
            Assert.Equal(endpoints[0].DataSetWriterId, "Leaf0_10000_3085991c-b85c-4311-9bfb-a916da952234");
            Assert.Equal(endpoints[0].Tag, "Tag_Leaf0_10000_3085991c-b85c-4311-9bfb-a916da952234");

            Assert.Equal(endpoints[1].DataSetWriterGroup, "Leaf1");
            Assert.Equal(endpoints[1].EndpointUrl, new Uri("opc.tcp://opcplc:50000"));
            Assert.Equal(endpoints[1].UseSecurity, false);
            Assert.Equal(endpoints[1].OpcAuthenticationMode, OpcAuthenticationMode.UsernamePassword);
            Assert.Equal(endpoints[1].DataSetWriterId, "Leaf1_10000_2e4fc28f-ffa2-4532-9f22-378d47bbee5d");
            Assert.Equal(endpoints[1].Tag, "Tag_Leaf1_10000_2e4fc28f-ffa2-4532-9f22-378d47bbee5d");
            endpoints[0].OpcNodes = null;
            var nodes = await _standaloneJobOrchestrator.GetConfiguredNodesOnEndpointAsync(endpoints[0]).ConfigureAwait(false);

            Assert.Equal(1, nodes.Count);
            Assert.Equal("nsu=http://microsoft.com/Opc/OpcPlc/;s=StepUp", nodes[0].Id);

            endpoints[0].OpcNodes = new List <OpcNodeModel>();
            endpoints[0].OpcNodes.Add(new OpcNodeModel {
                Id = "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt2",
            });

            await _standaloneJobOrchestrator.PublishNodesAsync(endpoints[0]).ConfigureAwait(false);

            endpoints = await _standaloneJobOrchestrator.GetConfiguredEndpointsAsync().ConfigureAwait(false);

            Assert.Equal(2, endpoints.Count);

            endpoints[0].OpcNodes = null;
            nodes = await _standaloneJobOrchestrator.GetConfiguredNodesOnEndpointAsync(endpoints[0]).ConfigureAwait(false);

            Assert.Equal(2, nodes.Count);
            Assert.Equal("nsu=http://microsoft.com/Opc/OpcPlc/;s=StepUp", nodes[0].Id);
            Assert.Equal("nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt2", nodes[1].Id);

            // Simulate restart.
            _standaloneJobOrchestrator.Dispose();
            _standaloneJobOrchestrator = null;
            InitStandaloneJobOrchestrator();

            // We should get the same endpoint and nodes after restart.
            endpoints = await _standaloneJobOrchestrator.GetConfiguredEndpointsAsync().ConfigureAwait(false);

            Assert.Equal(2, endpoints.Count);

            Assert.Equal(endpoints[0].DataSetWriterGroup, "Leaf0");
            Assert.Equal(endpoints[0].EndpointUrl, new Uri("opc.tcp://opcplc:50000"));
            Assert.Equal(endpoints[0].UseSecurity, false);
            Assert.Equal(endpoints[0].OpcAuthenticationMode, OpcAuthenticationMode.Anonymous);
            Assert.Equal(endpoints[0].DataSetWriterId, "Leaf0_10000_3085991c-b85c-4311-9bfb-a916da952234");
            Assert.Equal(endpoints[0].Tag, "Tag_Leaf0_10000_3085991c-b85c-4311-9bfb-a916da952234");

            nodes = await _standaloneJobOrchestrator.GetConfiguredNodesOnEndpointAsync(endpoints[0]).ConfigureAwait(false);

            Assert.Equal(2, nodes.Count);
            Assert.Equal("nsu=http://microsoft.com/Opc/OpcPlc/;s=StepUp", nodes[0].Id);
            Assert.Equal("nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt2", nodes[1].Id);
        }