public void WhenDnsFeatureStopped_ThenDnsServerSuccessfullyStops()
        {
            // Arrange.
            var dnsServer = new Mock <IDnsServer>();
            Action <int, CancellationToken> action = (port, token) =>
            {
                while (true)
                {
                    token.ThrowIfCancellationRequested();
                    Thread.Sleep(50);
                }
            };

            dnsServer.Setup(s => s.ListenAsync(It.IsAny <int>(), It.IsAny <CancellationToken>())).Callback(action);

            var mockWhitelistManager           = new Mock <IWhitelistManager>();
            IWhitelistManager whitelistManager = mockWhitelistManager.Object;

            var source       = new CancellationTokenSource();
            var nodeLifetime = new Mock <INodeLifetime>();

            nodeLifetime.Setup(n => n.StopApplication()).Callback(() => source.Cancel());
            nodeLifetime.Setup(n => n.ApplicationStopping).Returns(source.Token);
            INodeLifetime nodeLifetimeObject = nodeLifetime.Object;

            var        nodeSettings = new NodeSettings(args: new string[] { $"-datadir={ Directory.GetCurrentDirectory() }" });
            DataFolder dataFolder   = CreateDataFolder(this);

            var logger        = new Mock <ILogger>(MockBehavior.Loose);
            var loggerFactory = new Mock <ILoggerFactory>();

            loggerFactory.Setup <ILogger>(f => f.CreateLogger(It.IsAny <string>())).Returns(logger.Object);

            IAsyncLoopFactory asyncLoopFactory = new AsyncLoopFactory(loggerFactory.Object);

            // Act.
            var feature = new DnsFeature(dnsServer.Object, whitelistManager, loggerFactory.Object, nodeLifetimeObject, new DnsSettings(nodeSettings), nodeSettings, dataFolder, asyncLoopFactory);

            feature.InitializeAsync().GetAwaiter().GetResult();
            nodeLifetimeObject.StopApplication();
            bool waited = source.Token.WaitHandle.WaitOne(5000);

            // Assert.
            feature.Should().NotBeNull();
            waited.Should().BeTrue();
            dnsServer.Verify(s => s.ListenAsync(It.IsAny <int>(), It.IsAny <CancellationToken>()), Times.Once);
        }
        public void WhenDnsServerFailsToStart_ThenDnsFeatureRetries()
        {
            // Arrange.
            var dnsServer = new Mock <IDnsServer>();
            Action <int, CancellationToken> action = (port, token) =>
            {
                throw new ArgumentException("Bad port");
            };

            dnsServer.Setup(s => s.ListenAsync(It.IsAny <int>(), It.IsAny <CancellationToken>())).Callback(action);

            var mockWhitelistManager           = new Mock <IWhitelistManager>();
            IWhitelistManager whitelistManager = mockWhitelistManager.Object;

            var source       = new CancellationTokenSource(3000);
            var nodeLifetime = new Mock <INodeLifetime>();

            nodeLifetime.Setup(n => n.StopApplication()).Callback(() => source.Cancel());
            nodeLifetime.Setup(n => n.ApplicationStopping).Returns(source.Token);
            INodeLifetime nodeLifetimeObject = nodeLifetime.Object;

            var        nodeSettings = new NodeSettings(args: new string[] { $"-datadir={ Directory.GetCurrentDirectory() }" });
            DataFolder dataFolder   = CreateDataFolder(this);

            var  logger      = new Mock <ILogger>();
            bool serverError = false;

            logger.Setup(l => l.Log(LogLevel.Error, It.IsAny <EventId>(), It.IsAny <FormattedLogValues>(), It.IsAny <Exception>(), It.IsAny <Func <object, Exception, string> >())).Callback <LogLevel, EventId, object, Exception, Func <object, Exception, string> >((level, id, state, e, f) => serverError = state.ToString().StartsWith("Failed whilst running the DNS server"));
            var loggerFactory = new Mock <ILoggerFactory>();

            loggerFactory.Setup <ILogger>(f => f.CreateLogger(It.IsAny <string>())).Returns(logger.Object);

            IAsyncLoopFactory asyncLoopFactory = new AsyncLoopFactory(loggerFactory.Object);

            // Act.
            var feature = new DnsFeature(dnsServer.Object, whitelistManager, loggerFactory.Object, nodeLifetimeObject, new DnsSettings(nodeSettings), nodeSettings, dataFolder, asyncLoopFactory);

            feature.InitializeAsync().GetAwaiter().GetResult();
            bool waited = source.Token.WaitHandle.WaitOne(5000);

            // Assert.
            feature.Should().NotBeNull();
            waited.Should().BeTrue();
            dnsServer.Verify(s => s.ListenAsync(It.IsAny <int>(), It.IsAny <CancellationToken>()), Times.AtLeastOnce);
            serverError.Should().BeTrue();
        }
        public void WhenInitialize_ThenRefreshLoopIsStarted()
        {
            // Arrange.
            var mockWhitelistManager = new Mock <IWhitelistManager>();

            mockWhitelistManager.Setup(w => w.RefreshWhitelist()).Verifiable("the RefreshWhitelist method should be called on the WhitelistManager");

            IWhitelistManager whitelistManager = mockWhitelistManager.Object;

            var mockLogger        = new Mock <ILogger>();
            var mockLoggerFactory = new Mock <ILoggerFactory>();

            mockLoggerFactory.Setup(l => l.CreateLogger(It.IsAny <string>())).Returns(mockLogger.Object);
            ILoggerFactory loggerFactory = mockLoggerFactory.Object;

            IAsyncLoopFactory asyncLoopFactory = new AsyncLoopFactory(loggerFactory);
            INodeLifetime     nodeLifeTime     = new NodeLifetime();

            IDnsServer dnsServer = new Mock <IDnsServer>().Object;

            var source       = new CancellationTokenSource(3000);
            var nodeLifetime = new Mock <INodeLifetime>();

            nodeLifetime.Setup(n => n.StopApplication()).Callback(() => source.Cancel());
            nodeLifetime.Setup(n => n.ApplicationStopping).Returns(source.Token);
            INodeLifetime nodeLifetimeObject = nodeLifetime.Object;

            var        nodeSettings = new NodeSettings(args: new string[] { $"-datadir={ Directory.GetCurrentDirectory() }" });
            DataFolder dataFolder   = CreateDataFolder(this);

            using (var feature = new DnsFeature(dnsServer, whitelistManager, loggerFactory, nodeLifetimeObject, new DnsSettings(nodeSettings), nodeSettings, dataFolder, asyncLoopFactory))
            {
                // Act.
                feature.InitializeAsync().GetAwaiter().GetResult();
                bool waited = source.Token.WaitHandle.WaitOne(5000);

                // Assert.
                feature.Should().NotBeNull();
                waited.Should().BeTrue();
                mockWhitelistManager.Verify();
            }
        }
        public void WhenDnsFeatureInitialized_ThenDnsServerSuccessfullyStarts()
        {
            // Arrange.
            var dnsServer  = new Mock <IDnsServer>();
            var waitObject = new ManualResetEventSlim(false);
            Action <int, CancellationToken> action = (port, token) =>
            {
                waitObject.Set();
                throw new OperationCanceledException();
            };

            dnsServer.Setup(s => s.ListenAsync(It.IsAny <int>(), It.IsAny <CancellationToken>())).Callback(action);

            var whitelistManager = new Mock <IWhitelistManager>();

            var        nodeLifetime = new Mock <INodeLifetime>();
            var        nodeSettings = new NodeSettings(args: new string[] { $"-datadir={Directory.GetCurrentDirectory()}" });
            DataFolder dataFolder   = CreateDataFolder(this);

            var logger        = new Mock <ILogger>(MockBehavior.Loose);
            var loggerFactory = new Mock <ILoggerFactory>();

            loggerFactory.Setup <ILogger>(f => f.CreateLogger(It.IsAny <string>())).Returns(logger.Object);

            IAsyncLoopFactory asyncLoopFactory = new AsyncLoopFactory(loggerFactory.Object);

            // Act.
            var feature = new DnsFeature(dnsServer.Object, whitelistManager.Object, loggerFactory.Object, nodeLifetime.Object, new DnsSettings(nodeSettings), nodeSettings, dataFolder, asyncLoopFactory);

            feature.InitializeAsync().GetAwaiter().GetResult();
            bool waited = waitObject.Wait(5000);

            // Assert.
            feature.Should().NotBeNull();
            waited.Should().BeTrue();
            dnsServer.Verify(s => s.ListenAsync(It.IsAny <int>(), It.IsAny <CancellationToken>()), Times.Once);
        }