public async Task WhenDnsServerListening_AndDnsBadRequestReceived_ThenDnsServerFailsToProcessesRequest_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()).ReturnsAsync(new Tuple <IPEndPoint, byte[]>(new IPEndPoint(IPAddress.Loopback, 80), this.GetBadDnsRequest())); 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"); } }); bool receivedBadRequest = false; logger.Setup(l => l.Log(LogLevel.Warning, 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 warning message we were looking for if (!receivedBadRequest) { // Not yet set, check warning message receivedBadRequest = state.ToString().StartsWith("Failed to process DNS request"); } }); 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(); receivedBadRequest.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 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(); nodeSettings.DnsHostName = "host.example.com"; nodeSettings.DnsNameServer = "ns1.host.example.com"; nodeSettings.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, nodeSettings, 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_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; NodeSettings nodeSettings = NodeSettings.Default(); nodeSettings.DataDir = Directory.GetCurrentDirectory(); nodeSettings.DnsHostName = "host.example.com"; nodeSettings.DnsNameServer = "ns1.host.example.com"; nodeSettings.DnsMailBox = "*****@*****.**"; DataFolder dataFolders = new Mock <DataFolder>(nodeSettings).Object; 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, nodeSettings, dataFolders); 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(); } }
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); }