Beispiel #1
0
        public void WhenDnsServerInitialized_AndMasterFileOnDisk_ThenDnsServerSuccessfullyInitializes()
        {
            // Arrange.
            Mock <IUdpClient>  udpClient  = new Mock <IUdpClient>();
            Mock <IMasterFile> masterFile = new Mock <IMasterFile>();

            masterFile.Setup(m => m.Get(It.IsAny <Question>())).Returns(new List <IResourceRecord>());

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

            nodeLifetime.Setup(n => n.ApplicationStopping).Returns(source.Token);

            Mock <ILogger>        logger        = new Mock <ILogger>();
            Mock <ILoggerFactory> loggerFactory = new Mock <ILoggerFactory>();

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

            Mock <IAsyncLoopFactory> asyncLoopFactory = new Mock <IAsyncLoopFactory>();

            asyncLoopFactory.Setup(f => f.Run(It.IsAny <string>(), It.IsAny <Func <CancellationToken, Task> >(), It.IsAny <TimeSpan?>(), It.IsAny <TimeSpan?>())).Returns(new Mock <IAsyncLoop>().Object);

            IDateTimeProvider dateTimeProvider = new Mock <IDateTimeProvider>().Object;
            DnsSettings       dnsSettings      = new Mock <DnsSettings>().Object;

            dnsSettings.DnsHostName   = "host.example.com";
            dnsSettings.DnsNameServer = "ns1.host.example.com";
            dnsSettings.DnsMailBox    = "*****@*****.**";
            DataFolder dataFolder = CreateDataFolder(this);

            string masterFilePath = Path.Combine(dataFolder.DnsMasterFilePath, DnsFeature.DnsMasterFileName);

            // Act.
            try
            {
                // Create masterfile on disk
                using (FileStream stream = File.Create(masterFilePath))
                {
                    stream.Close();
                }

                // Run server
                DnsSeedServer server = new DnsSeedServer(udpClient.Object, masterFile.Object, asyncLoopFactory.Object, nodeLifetime.Object, loggerFactory.Object, dateTimeProvider, dnsSettings, dataFolder);
                server.Initialize();
                bool waited = source.Token.WaitHandle.WaitOne();

                // Assert.
                server.Should().NotBeNull();
                waited.Should().BeTrue();
                masterFile.Verify(m => m.Load(It.IsAny <Stream>()), Times.Once);
            }
            finally
            {
                // Try and remove created
                if (File.Exists(masterFilePath))
                {
                    File.Delete(masterFilePath);
                }
            }
        }
        public void WhenDnsServerInitialized_ThenMetricsLoopStarted()
        {
            // Arrange.
            Mock <IUdpClient>  udpClient  = new Mock <IUdpClient>();
            Mock <IMasterFile> masterFile = new Mock <IMasterFile>();

            masterFile.Setup(m => m.Get(It.IsAny <Question>())).Returns(new List <IResourceRecord>());

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

            nodeLifetime.Setup(n => n.ApplicationStopping).Returns(source.Token);

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

            logger.Setup(l => l.Log(LogLevel.Information, 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) =>
            {
                // Don't reset if we found the trace message we were looking for
                if (!startedLoop)
                {
                    // Not yet set, check trace message
                    startedLoop = state.ToString().Contains("DNS Metrics");
                }
            });
            Mock <ILoggerFactory> loggerFactory = new Mock <ILoggerFactory>();

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

            IAsyncLoopFactory asyncLoopFactory = new AsyncLoopFactory(loggerFactory.Object);

            IDateTimeProvider dateTimeProvider = new Mock <IDateTimeProvider>().Object;
            NodeSettings      nodeSettings     = NodeSettings.Default();

            nodeSettings.DataDir = Directory.GetCurrentDirectory();
            DnsSettings dnsSettings = new Mock <DnsSettings>().Object;

            dnsSettings.DnsHostName   = "host.example.com";
            dnsSettings.DnsNameServer = "ns1.host.example.com";
            dnsSettings.DnsMailBox    = "*****@*****.**";
            DataFolder dataFolders = new Mock <DataFolder>(nodeSettings).Object;

            // Act.
            DnsSeedServer server = new DnsSeedServer(udpClient.Object, masterFile.Object, asyncLoopFactory, nodeLifetime.Object, loggerFactory.Object, dateTimeProvider, dnsSettings, dataFolders);

            server.Initialize();
            bool waited = source.Token.WaitHandle.WaitOne();

            // Assert.
            server.Should().NotBeNull();
            waited.Should().BeTrue();
            startedLoop.Should().BeTrue();
        }
        public void WhenDnsServerInitialized_ThenMetricsLoopStarted()
        {
            // Arrange.
            var udpClient  = new Mock <IUdpClient>();
            var masterFile = new Mock <IMasterFile>();

            masterFile.Setup(m => m.Get(It.IsAny <Question>())).Returns(new List <IResourceRecord>());

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

            nodeLifetime.Setup(n => n.ApplicationStopping).Returns(source.Token);

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

            logger
            .Setup(f => f.Log(It.IsAny <LogLevel>(), It.IsAny <EventId>(), It.IsAny <It.IsAnyType>(), It.IsAny <Exception>(), (Func <It.IsAnyType, Exception, string>)It.IsAny <object>()))
            .Callback(new InvocationAction(invocation =>
            {
                if (!startedLoop && (LogLevel)invocation.Arguments[0] == LogLevel.Information)
                {
                    // Not yet set, check trace message
                    startedLoop = invocation.Arguments[2].ToString().Contains("DNS Metrics");
                }
            }));
            var loggerFactory = new Mock <ILoggerFactory>();

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

            IAsyncProvider asyncProvider = new AsyncProvider(loggerFactory.Object, new Mock <ISignals>().Object);

            IDateTimeProvider dateTimeProvider = new Mock <IDateTimeProvider>().Object;
            DnsSettings       dnsSettings      = new DnsSettings(NodeSettings.Default(this.Network));

            dnsSettings.DnsHostName   = "host.example.com";
            dnsSettings.DnsNameServer = "ns1.host.example.com";
            dnsSettings.DnsMailBox    = "*****@*****.**";
            DataFolder dataFolder = CreateDataFolder(this);

            // Act.
            var server = new DnsSeedServer(udpClient.Object, masterFile.Object, asyncProvider, nodeLifetime.Object, loggerFactory.Object, dateTimeProvider, dnsSettings, dataFolder);

            server.Initialize();
            bool waited = source.Token.WaitHandle.WaitOne();

            // Assert.
            server.Should().NotBeNull();
            waited.Should().BeTrue();
            startedLoop.Should().BeTrue();
        }
Beispiel #4
0
        public void WhenDnsServerInitialized_AndNoMasterFileOnDisk_ThenDnsServerSuccessfullyInitializes()
        {
            // Arrange.
            var udpClient  = new Mock <IUdpClient>();
            var masterFile = new Mock <IMasterFile>();

            masterFile.Setup(m => m.Get(It.IsAny <Question>())).Returns(new List <IResourceRecord>());

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

            nodeLifetime.Setup(n => n.ApplicationStopping).Returns(source.Token);

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

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

            var asyncProvider = new Mock <IAsyncProvider>();

            asyncProvider.Setup(f => f.CreateAndRunAsyncLoop(It.IsAny <string>(), It.IsAny <Func <CancellationToken, Task> >(), CancellationToken.None, It.IsAny <TimeSpan?>(), It.IsAny <TimeSpan?>())).Returns(new Mock <IAsyncLoop>().Object);

            IDateTimeProvider dateTimeProvider = new Mock <IDateTimeProvider>().Object;
            DnsSettings       dnsSettings      = new DnsSettings(NodeSettings.Default(this.Network));

            dnsSettings.DnsHostName   = "host.example.com";
            dnsSettings.DnsNameServer = "ns1.host.example.com";
            dnsSettings.DnsMailBox    = "*****@*****.**";
            DataFolder dataFolder = CreateDataFolder(this);

            string masterFilePath = Path.Combine(dataFolder.DnsMasterFilePath, DnsFeature.DnsMasterFileName);

            // Try and remove if already exists
            if (File.Exists(masterFilePath))
            {
                File.Delete(masterFilePath);
            }

            // Act.
            var server = new DnsSeedServer(udpClient.Object, masterFile.Object, asyncProvider.Object, nodeLifetime.Object, loggerFactory.Object, dateTimeProvider, dnsSettings, dataFolder);

            server.Initialize();
            bool waited = source.Token.WaitHandle.WaitOne();

            // Assert.
            server.Should().NotBeNull();
            waited.Should().BeTrue();
            masterFile.Verify(m => m.Load(It.IsAny <Stream>()), Times.Never);
        }
Beispiel #5
0
        public void WhenConstructorCalled_AndAllParametersValid_ThenTypeCreated()
        {
            // Arrange.
            IUdpClient        udpClient        = new Mock <IUdpClient>().Object;
            IMasterFile       masterFile       = new Mock <IMasterFile>().Object;
            IAsyncLoopFactory asyncLoopFactory = new Mock <IAsyncLoopFactory>().Object;
            INodeLifetime     nodeLifetime     = new Mock <INodeLifetime>().Object;
            ILoggerFactory    loggerFactory    = new Mock <ILoggerFactory>().Object;
            IDateTimeProvider dateTimeProvider = new Mock <IDateTimeProvider>().Object;
            NodeSettings      nodeSettings     = NodeSettings.Default();
            DataFolder        dataFolder       = CreateDataFolder(this);

            // Act.
            DnsSeedServer server = new DnsSeedServer(udpClient, masterFile, asyncLoopFactory, nodeLifetime, loggerFactory, dateTimeProvider, new DnsSettings().Load(nodeSettings), dataFolder);

            // Assert.
            server.Should().NotBeNull();
        }
        public void WhenDnsServerInitialized_ThenSaveMasterfileLoopStarted()
        {
            // Arrange.
            Mock <IUdpClient>  udpClient  = new Mock <IUdpClient>();
            Mock <IMasterFile> masterFile = new Mock <IMasterFile>();

            masterFile.Setup(m => m.Get(It.IsAny <Question>())).Returns(new List <IResourceRecord>());
            masterFile.Setup(m => m.Save(It.IsAny <Stream>())).Verifiable();

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

            nodeLifetime.Setup(n => n.ApplicationStopping).Returns(source.Token);

            Mock <ILogger>        logger        = new Mock <ILogger>();
            Mock <ILoggerFactory> loggerFactory = new Mock <ILoggerFactory>();

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

            IAsyncLoopFactory asyncLoopFactory = new AsyncLoopFactory(loggerFactory.Object);

            IDateTimeProvider dateTimeProvider = new Mock <IDateTimeProvider>().Object;
            NodeSettings      nodeSettings     = NodeSettings.Default();

            nodeSettings.DataDir = Directory.GetCurrentDirectory();
            DnsSettings dnsSettings = new Mock <DnsSettings>().Object;

            dnsSettings.DnsHostName   = "host.example.com";
            dnsSettings.DnsNameServer = "ns1.host.example.com";
            dnsSettings.DnsMailBox    = "*****@*****.**";
            DataFolder dataFolders = new Mock <DataFolder>(nodeSettings).Object;

            // Act.
            DnsSeedServer server = new DnsSeedServer(udpClient.Object, masterFile.Object, asyncLoopFactory, nodeLifetime.Object, loggerFactory.Object, dateTimeProvider, dnsSettings, dataFolders);

            server.Initialize();
            bool waited = source.Token.WaitHandle.WaitOne();

            // Assert.
            server.Should().NotBeNull();
            waited.Should().BeTrue();
            masterFile.Verify(m => m.Save(It.IsAny <Stream>()), Times.AtLeastOnce);
        }
        public void WhenDnsServerListening_AndSocketExceptionRaised_ThenDnsServerFailsToStart()
        {
            // Arrange.
            Mock <IUdpClient> udpClient = new Mock <IUdpClient>();

            udpClient.Setup(c => c.StartListening(It.IsAny <int>())).Throws(new SocketException());

            Mock <IMasterFile> masterFile = new Mock <IMasterFile>();

            IAsyncLoopFactory asyncLoopFactory = new Mock <IAsyncLoopFactory>().Object;
            INodeLifetime     nodeLifetime     = new Mock <INodeLifetime>().Object;

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

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

            IDateTimeProvider dateTimeProvider = new Mock <IDateTimeProvider>().Object;
            NodeSettings      nodeSettings     = NodeSettings.Default();

            nodeSettings.DataDir = Directory.GetCurrentDirectory();
            DnsSettings dnsSettings = new Mock <DnsSettings>().Object;

            dnsSettings.DnsHostName   = "host.example.com";
            dnsSettings.DnsNameServer = "ns1.host.example.com";
            dnsSettings.DnsMailBox    = "*****@*****.**";
            DataFolder dataFolders = new Mock <DataFolder>(nodeSettings).Object;

            // Act.
            CancellationTokenSource source = new CancellationTokenSource();
            DnsSeedServer           server = new DnsSeedServer(udpClient.Object, masterFile.Object, asyncLoopFactory, nodeLifetime, loggerFactory.Object, dateTimeProvider, dnsSettings, dataFolders);
            Func <Task>             func   = async() => await server.ListenAsync(53, source.Token);

            // Assert.
            server.Should().NotBeNull();
            func.ShouldThrow <SocketException>();
            server.Metrics.DnsServerFailureCountSinceStart.Should().Be(1);
            server.Metrics.CurrentSnapshot.DnsServerFailureCountSinceLastPeriod.Should().Be(1);
        }
Beispiel #8
0
        public async Task WhenDnsServerListening_AndDnsRequestReceivedRepeatedly_ThenResponsesReturnedInRoundRobinOrder_Async()
        {
            // Arrange.
            Queue <CancellationTokenSource> sources = new Queue <CancellationTokenSource>();
            Queue <byte[]>    responses             = new Queue <byte[]>();
            Mock <IUdpClient> udpClient             = new Mock <IUdpClient>();

            udpClient.Setup(c => c.ReceiveAsync()).ReturnsAsync(new Tuple <IPEndPoint, byte[]>(new IPEndPoint(IPAddress.Loopback, 80), this.GetDnsRequest()));
            udpClient.Setup(c => c.SendAsync(It.IsAny <byte[]>(), It.IsAny <int>(), It.IsAny <IPEndPoint>())).Callback <byte[], int, IPEndPoint>((p, s, ip) =>
            {
                // One response at a time.
                responses.Enqueue(p);
                CancellationTokenSource source = sources.Dequeue();
                source.Cancel();
            }).ReturnsAsync(1);

            DnsSeedMasterFile masterFile = new DnsSeedMasterFile();

            masterFile.Add(new IPAddressResourceRecord(new Domain("google.com"), IPAddress.Parse("192.168.0.1")));
            masterFile.Add(new IPAddressResourceRecord(new Domain("google.com"), IPAddress.Parse("192.168.0.2")));
            masterFile.Add(new IPAddressResourceRecord(new Domain("google.com"), IPAddress.Parse("192.168.0.3")));
            masterFile.Add(new IPAddressResourceRecord(new Domain("google.com"), IPAddress.Parse("192.168.0.4")));

            IAsyncLoopFactory asyncLoopFactory = new Mock <IAsyncLoopFactory>().Object;
            INodeLifetime     nodeLifetime     = new Mock <INodeLifetime>().Object;
            DnsSettings       dnsSettings      = new Mock <DnsSettings>().Object;

            dnsSettings.DnsHostName   = "host.example.com";
            dnsSettings.DnsNameServer = "ns1.host.example.com";
            dnsSettings.DnsMailBox    = "*****@*****.**";
            DataFolder dataFolder = CreateDataFolder(this);

            Mock <ILogger>        logger        = new Mock <ILogger>();
            Mock <ILoggerFactory> loggerFactory = new Mock <ILoggerFactory>();

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

            IDateTimeProvider dateTimeProvider = new Mock <IDateTimeProvider>().Object;

            // Act (Part 1).
            DnsSeedServer server = new DnsSeedServer(udpClient.Object, masterFile, asyncLoopFactory, nodeLifetime, loggerFactory.Object, dateTimeProvider, dnsSettings, dataFolder);

            try
            {
                CancellationTokenSource source = new CancellationTokenSource();
                sources.Enqueue(source);
                await server.ListenAsync(53, source.Token);
            }
            catch (OperationCanceledException)
            {
                // Expected.
            }

            // Assert (Part 1).
            responses.Count.Should().Be(1);
            byte[]    response    = responses.Dequeue();
            IResponse dnsResponse = Response.FromArray(response);

            dnsResponse.AnswerRecords.Count.Should().Be(4);
            dnsResponse.AnswerRecords[0].Should().BeOfType <IPAddressResourceRecord>();

            ((IPAddressResourceRecord)dnsResponse.AnswerRecords[0]).IPAddress.ToString().Should().Be("192.168.0.1");

            while (responses.Count > 0)
            {
                // Consume queue completely.
                responses.Dequeue();
            }

            // Act (Part 2).
            try
            {
                CancellationTokenSource source = new CancellationTokenSource();
                sources.Enqueue(source);
                await server.ListenAsync(53, source.Token);
            }
            catch (OperationCanceledException)
            {
                // Expected.
            }

            // Assert (Part 2).
            responses.Count.Should().Be(1);
            response    = responses.Dequeue();
            dnsResponse = Response.FromArray(response);

            dnsResponse.AnswerRecords.Count.Should().Be(4);
            dnsResponse.AnswerRecords[0].Should().BeOfType <IPAddressResourceRecord>();

            ((IPAddressResourceRecord)dnsResponse.AnswerRecords[0]).IPAddress.ToString().Should().Be("192.168.0.2");

            while (responses.Count > 0)
            {
                // Consume queue completely.
                responses.Dequeue();
            }

            // Act (Part 3).
            try
            {
                CancellationTokenSource source = new CancellationTokenSource();
                sources.Enqueue(source);
                await server.ListenAsync(53, source.Token);
            }
            catch (OperationCanceledException)
            {
                // Expected.
            }

            // Assert (Part 3).
            responses.Count.Should().Be(1);
            response    = responses.Dequeue();
            dnsResponse = Response.FromArray(response);

            dnsResponse.AnswerRecords.Count.Should().Be(4);
            dnsResponse.AnswerRecords[0].Should().BeOfType <IPAddressResourceRecord>();

            ((IPAddressResourceRecord)dnsResponse.AnswerRecords[0]).IPAddress.ToString().Should().Be("192.168.0.3");

            while (responses.Count > 0)
            {
                // Consume queue completely.
                responses.Dequeue();
            }

            // Act (Part 4).
            try
            {
                CancellationTokenSource source = new CancellationTokenSource();
                sources.Enqueue(source);
                await server.ListenAsync(53, source.Token);
            }
            catch (OperationCanceledException)
            {
                // Expected.
            }

            // Assert (Part 4).
            responses.Count.Should().Be(1);
            response    = responses.Dequeue();
            dnsResponse = Response.FromArray(response);

            dnsResponse.AnswerRecords.Count.Should().Be(4);
            dnsResponse.AnswerRecords[0].Should().BeOfType <IPAddressResourceRecord>();

            ((IPAddressResourceRecord)dnsResponse.AnswerRecords[0]).IPAddress.ToString().Should().Be("192.168.0.4");

            while (responses.Count > 0)
            {
                // Consume queue completely.
                responses.Dequeue();
            }

            // Act (Part 5).
            try
            {
                CancellationTokenSource source = new CancellationTokenSource();
                sources.Enqueue(source);
                await server.ListenAsync(53, source.Token);
            }
            catch (OperationCanceledException)
            {
                // Expected.
            }

            // Assert (Part 5).
            responses.Count.Should().Be(1);
            response    = responses.Dequeue();
            dnsResponse = Response.FromArray(response);

            dnsResponse.AnswerRecords.Count.Should().Be(4);
            dnsResponse.AnswerRecords[0].Should().BeOfType <IPAddressResourceRecord>();

            // This should start back at the beginning again.
            ((IPAddressResourceRecord)dnsResponse.AnswerRecords[0]).IPAddress.ToString().Should().Be("192.168.0.1");

            while (responses.Count > 0)
            {
                // Consume queue completely.
                responses.Dequeue();
            }
        }
Beispiel #9
0
        public async Task WhenDnsServerListening_AndDnsRequestReceived_ThenDnsServerSuccessfullyProcessesRequest_Async()
        {
            // Arrange.
            bool startedListening       = false;
            bool sentResponse           = false;
            Mock <IUdpClient> udpClient = new Mock <IUdpClient>();

            udpClient.Setup(c => c.StartListening(It.IsAny <int>())).Callback(() => startedListening = true);
            udpClient.Setup(c => c.ReceiveAsync()).ReturnsAsync(new Tuple <IPEndPoint, byte[]>(new IPEndPoint(IPAddress.Loopback, 80), this.GetDnsRequest()));
            udpClient.Setup(c => c.SendAsync(It.IsAny <byte[]>(), It.IsAny <int>(), It.IsAny <IPEndPoint>())).Callback <byte[], int, IPEndPoint>((p, s, ip) => sentResponse = true).ReturnsAsync(1);

            Mock <IMasterFile> masterFile = new Mock <IMasterFile>();

            masterFile.Setup(m => m.Get(It.IsAny <Question>())).Returns(new List <IResourceRecord>()
            {
                new IPAddressResourceRecord(Domain.FromString("google.com"), IPAddress.Loopback)
            });

            IAsyncLoopFactory asyncLoopFactory = new Mock <IAsyncLoopFactory>().Object;
            INodeLifetime     nodeLifetime     = new Mock <INodeLifetime>().Object;
            DnsSettings       dnsSettings      = new Mock <DnsSettings>().Object;

            dnsSettings.DnsHostName   = "host.example.com";
            dnsSettings.DnsNameServer = "ns1.host.example.com";
            dnsSettings.DnsMailBox    = "*****@*****.**";
            DataFolder dataFolder = CreateDataFolder(this);

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

            logger.Setup(l => l.Log(LogLevel.Trace, 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) =>
            {
                // Don't reset if we found the trace message we were looking for
                if (!receivedRequest)
                {
                    // Not yet set, check trace message
                    receivedRequest = state.ToString().StartsWith("DNS request received");
                }
            });
            Mock <ILoggerFactory> loggerFactory = new Mock <ILoggerFactory>();

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

            IDateTimeProvider dateTimeProvider = new Mock <IDateTimeProvider>().Object;

            // Act.
            CancellationTokenSource source = new CancellationTokenSource(2000);
            DnsSeedServer           server = new DnsSeedServer(udpClient.Object, masterFile.Object, asyncLoopFactory, nodeLifetime, loggerFactory.Object, dateTimeProvider, dnsSettings, dataFolder);

            try
            {
                await server.ListenAsync(53, source.Token);
            }
            catch (OperationCanceledException)
            {
                // Expected
            }

            // Assert.
            server.Should().NotBeNull();
            startedListening.Should().BeTrue();
            receivedRequest.Should().BeTrue();
            sentResponse.Should().BeTrue();
            server.Metrics.DnsRequestCountSinceStart.Should().BeGreaterThan(0);
            server.Metrics.DnsRequestFailureCountSinceStart.Should().Be(0);
            server.Metrics.DnsServerFailureCountSinceStart.Should().Be(0);
            server.Metrics.CurrentSnapshot.DnsRequestCountSinceLastPeriod.Should().BeGreaterThan(0);
            server.Metrics.CurrentSnapshot.DnsRequestFailureCountSinceLastPeriod.Should().Be(0);
            server.Metrics.CurrentSnapshot.DnsServerFailureCountSinceLastPeriod.Should().Be(0);
            server.Metrics.CurrentSnapshot.DnsRequestElapsedTicksSinceLastPeriod.Should().BeGreaterThan(0);
            server.Metrics.CurrentSnapshot.LastDnsRequestElapsedTicks.Should().BeGreaterThan(0);
        }
        public async Task WhenDnsServerReceiving_AndSocketExceptionRaised_ThenDnsServerFails_Async()
        {
            // Arrange.
            bool startedListening       = false;
            Mock <IUdpClient> udpClient = new Mock <IUdpClient>();

            udpClient.Setup(c => c.StartListening(It.IsAny <int>())).Callback(() => startedListening = true);
            udpClient.Setup(c => c.ReceiveAsync()).ThrowsAsync(new SocketException());

            Mock <IMasterFile> masterFile = new Mock <IMasterFile>();

            masterFile.Setup(m => m.Get(It.IsAny <Question>())).Returns(new List <IResourceRecord>()
            {
                new IPAddressResourceRecord(Domain.FromString("google.com"), IPAddress.Loopback)
            });

            IAsyncLoopFactory asyncLoopFactory = new Mock <IAsyncLoopFactory>().Object;
            INodeLifetime     nodeLifetime     = new Mock <INodeLifetime>().Object;
            NodeSettings      nodeSettings     = NodeSettings.Default();

            nodeSettings.DataDir = Directory.GetCurrentDirectory();
            DnsSettings dnsSettings = new Mock <DnsSettings>().Object;

            dnsSettings.DnsHostName   = "host.example.com";
            dnsSettings.DnsNameServer = "ns1.host.example.com";
            dnsSettings.DnsMailBox    = "*****@*****.**";
            DataFolder dataFolders = new Mock <DataFolder>(nodeSettings).Object;

            Mock <ILogger> logger = new Mock <ILogger>(MockBehavior.Loose);
            bool           receivedSocketException = 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) =>
            {
                // Don't reset if we found the error message we were looking for
                if (!receivedSocketException)
                {
                    // Not yet set, check error message
                    receivedSocketException = state.ToString().StartsWith("Socket exception");
                }
            });
            Mock <ILoggerFactory> loggerFactory = new Mock <ILoggerFactory>();

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

            IDateTimeProvider dateTimeProvider = new Mock <IDateTimeProvider>().Object;

            // Act.
            CancellationTokenSource source = new CancellationTokenSource(2000);
            DnsSeedServer           server = new DnsSeedServer(udpClient.Object, masterFile.Object, asyncLoopFactory, nodeLifetime, loggerFactory.Object, dateTimeProvider, dnsSettings, dataFolders);

            try
            {
                await server.ListenAsync(53, source.Token);
            }
            catch (OperationCanceledException)
            {
                // Expected
            }

            // Assert.
            server.Should().NotBeNull();
            startedListening.Should().BeTrue();
            receivedSocketException.Should().BeTrue();
            server.Metrics.DnsRequestCountSinceStart.Should().BeGreaterThan(0);
            server.Metrics.DnsRequestFailureCountSinceStart.Should().BeGreaterThan(0);
            server.Metrics.DnsServerFailureCountSinceStart.Should().Be(0);
            server.Metrics.CurrentSnapshot.DnsRequestCountSinceLastPeriod.Should().BeGreaterThan(0);
            server.Metrics.CurrentSnapshot.DnsRequestFailureCountSinceLastPeriod.Should().BeGreaterThan(0);
            server.Metrics.CurrentSnapshot.DnsServerFailureCountSinceLastPeriod.Should().Be(0);
        }
        public async Task WhenDnsServerListening_AndDnsRequestReceived_ThenDnsServerSuccessfullyProcessesRequest_Async()
        {
            // Arrange.
            bool startedListening = false;
            bool sentResponse     = false;
            var  udpClient        = new Mock <IUdpClient>();

            udpClient.Setup(c => c.StartListening(It.IsAny <int>())).Callback(() => startedListening = true);
            udpClient.Setup(c => c.ReceiveAsync()).ReturnsAsync(new Tuple <IPEndPoint, byte[]>(new IPEndPoint(IPAddress.Loopback, 80), this.GetDnsRequest()));
            udpClient.Setup(c => c.SendAsync(It.IsAny <byte[]>(), It.IsAny <int>(), It.IsAny <IPEndPoint>())).Callback <byte[], int, IPEndPoint>((p, s, ip) => sentResponse = true).ReturnsAsync(1);

            var masterFile = new Mock <IMasterFile>();

            masterFile.Setup(m => m.Get(It.IsAny <Question>())).Returns(new List <IResourceRecord>()
            {
                new IPAddressResourceRecord(Domain.FromString("google.com"), IPAddress.Loopback)
            });

            IAsyncProvider asyncProvider = new Mock <IAsyncProvider>().Object;
            INodeLifetime  nodeLifetime  = new Mock <INodeLifetime>().Object;
            DnsSettings    dnsSettings   = new DnsSettings(NodeSettings.Default(this.Network));

            dnsSettings.DnsHostName   = "host.example.com";
            dnsSettings.DnsNameServer = "ns1.host.example.com";
            dnsSettings.DnsMailBox    = "*****@*****.**";
            DataFolder dataFolder = CreateDataFolder(this);

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

            logger
            .Setup(f => f.Log(It.IsAny <LogLevel>(), It.IsAny <EventId>(), It.IsAny <It.IsAnyType>(), It.IsAny <Exception>(), (Func <It.IsAnyType, Exception, string>)It.IsAny <object>()))
            .Callback(new InvocationAction(invocation =>
            {
                if (!receivedRequest && (LogLevel)invocation.Arguments[0] == LogLevel.Debug)
                {
                    // Not yet set, check trace message
                    receivedRequest = invocation.Arguments[2].ToString().StartsWith("DNS request received");
                }
            }));
            var loggerFactory = new Mock <ILoggerFactory>();

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

            IDateTimeProvider dateTimeProvider = new Mock <IDateTimeProvider>().Object;

            // Act.
            var source = new CancellationTokenSource(2000);
            var server = new DnsSeedServer(udpClient.Object, masterFile.Object, asyncProvider, nodeLifetime, loggerFactory.Object, dateTimeProvider, dnsSettings, dataFolder);

            try
            {
                await server.ListenAsync(53, source.Token);
            }
            catch (OperationCanceledException)
            {
                // Expected
            }

            // Assert.
            server.Should().NotBeNull();
            startedListening.Should().BeTrue();
            receivedRequest.Should().BeTrue();
            sentResponse.Should().BeTrue();
            server.Metrics.DnsRequestCountSinceStart.Should().BeGreaterThan(0);
            server.Metrics.DnsRequestFailureCountSinceStart.Should().Be(0);
            server.Metrics.DnsServerFailureCountSinceStart.Should().Be(0);
            server.Metrics.CurrentSnapshot.DnsRequestCountSinceLastPeriod.Should().BeGreaterThan(0);
            server.Metrics.CurrentSnapshot.DnsRequestFailureCountSinceLastPeriod.Should().Be(0);
            server.Metrics.CurrentSnapshot.DnsServerFailureCountSinceLastPeriod.Should().Be(0);
            server.Metrics.CurrentSnapshot.DnsRequestElapsedTicksSinceLastPeriod.Should().BeGreaterThan(0);
            server.Metrics.CurrentSnapshot.LastDnsRequestElapsedTicks.Should().BeGreaterThan(0);
        }