PageRenderTime 35ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/MongoDB.Driver.Core.Tests/Core/Servers/ServerMonitorTests.cs

http://github.com/mongodb/mongo-csharp-driver
C# | 204 lines | 148 code | 36 blank | 20 comment | 6 complexity | 33928ca0eee71a053d58b77d7d276fa5 MD5 | raw file
Possible License(s): Apache-2.0
  1. /* Copyright 2016-present MongoDB Inc.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing,.Setup software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. using System;
  16. using System.Collections.Generic;
  17. using System.Net;
  18. using System.Threading;
  19. using FluentAssertions;
  20. using MongoDB.Bson;
  21. using MongoDB.Driver.Core.Bindings;
  22. using MongoDB.Driver.Core.Clusters;
  23. using MongoDB.Driver.Core.Configuration;
  24. using MongoDB.Driver.Core.ConnectionPools;
  25. using MongoDB.Driver.Core.Connections;
  26. using MongoDB.Driver.Core.Events;
  27. using MongoDB.Driver.Core.Helpers;
  28. using Moq;
  29. using Xunit;
  30. namespace MongoDB.Driver.Core.Servers
  31. {
  32. public class ServerMonitorTests
  33. {
  34. private EndPoint _endPoint;
  35. private MockConnection _connection;
  36. private Mock<IConnectionFactory> _mockConnectionFactory;
  37. private EventCapturer _capturedEvents;
  38. private ServerId _serverId;
  39. private ServerMonitor _subject;
  40. public ServerMonitorTests()
  41. {
  42. _endPoint = new DnsEndPoint("localhost", 27017);
  43. _serverId = new ServerId(new ClusterId(), _endPoint);
  44. _connection = new MockConnection();
  45. _mockConnectionFactory = new Mock<IConnectionFactory>();
  46. _mockConnectionFactory
  47. .Setup(f => f.CreateConnection(_serverId, _endPoint))
  48. .Returns(_connection);
  49. _capturedEvents = new EventCapturer();
  50. _subject = new ServerMonitor(_serverId, _endPoint, _mockConnectionFactory.Object, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan, _capturedEvents);
  51. }
  52. [Fact]
  53. public void Constructor_should_throw_when_serverId_is_null()
  54. {
  55. Action act = () => new ServerMonitor(null, _endPoint, _mockConnectionFactory.Object, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan, _capturedEvents);
  56. act.ShouldThrow<ArgumentNullException>();
  57. }
  58. [Fact]
  59. public void Constructor_should_throw_when_endPoint_is_null()
  60. {
  61. Action act = () => new ServerMonitor(_serverId, null, _mockConnectionFactory.Object, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan, _capturedEvents);
  62. act.ShouldThrow<ArgumentNullException>();
  63. }
  64. [Fact]
  65. public void Constructor_should_throw_when_connectionFactory_is_null()
  66. {
  67. Action act = () => new ServerMonitor(_serverId, _endPoint, null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan, _capturedEvents);
  68. act.ShouldThrow<ArgumentNullException>();
  69. }
  70. [Fact]
  71. public void Constructor_should_throw_when_eventSubscriber_is_null()
  72. {
  73. Action act = () => new ServerMonitor(_serverId, _endPoint, _mockConnectionFactory.Object, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan, null);
  74. act.ShouldThrow<ArgumentNullException>();
  75. }
  76. [Fact]
  77. public void Description_should_return_default_when_uninitialized()
  78. {
  79. var description = _subject.Description;
  80. description.EndPoint.Should().Be(_endPoint);
  81. description.Type.Should().Be(ServerType.Unknown);
  82. description.State.Should().Be(ServerState.Disconnected);
  83. }
  84. [Fact]
  85. public void Description_should_return_default_when_disposed()
  86. {
  87. _subject.Dispose();
  88. var description = _subject.Description;
  89. description.EndPoint.Should().Be(_endPoint);
  90. description.Type.Should().Be(ServerType.Unknown);
  91. description.State.Should().Be(ServerState.Disconnected);
  92. }
  93. [Fact]
  94. public void DescriptionChanged_should_be_raised_when_moving_from_disconnected_to_connected()
  95. {
  96. var changes = new List<ServerDescriptionChangedEventArgs>();
  97. _subject.DescriptionChanged += (o, e) => changes.Add(e);
  98. SetupHeartbeatConnection();
  99. _subject.Initialize();
  100. SpinWait.SpinUntil(() => _subject.Description.State == ServerState.Connected, TimeSpan.FromSeconds(5)).Should().BeTrue();
  101. changes.Count.Should().Be(1);
  102. changes[0].OldServerDescription.State.Should().Be(ServerState.Disconnected);
  103. changes[0].NewServerDescription.State.Should().Be(ServerState.Connected);
  104. _capturedEvents.Next().Should().BeOfType<ServerHeartbeatStartedEvent>();
  105. _capturedEvents.Next().Should().BeOfType<ServerHeartbeatSucceededEvent>();
  106. _capturedEvents.Any().Should().BeFalse();
  107. }
  108. [Fact]
  109. public void Description_should_be_connected_after_successful_heartbeat()
  110. {
  111. SetupHeartbeatConnection();
  112. _subject.Initialize();
  113. SpinWait.SpinUntil(() => _subject.Description.State == ServerState.Connected, TimeSpan.FromSeconds(5)).Should().BeTrue();
  114. _subject.Description.State.Should().Be(ServerState.Connected);
  115. _subject.Description.Type.Should().Be(ServerType.Standalone);
  116. _capturedEvents.Next().Should().BeOfType<ServerHeartbeatStartedEvent>();
  117. _capturedEvents.Next().Should().BeOfType<ServerHeartbeatSucceededEvent>();
  118. _capturedEvents.Any().Should().BeFalse();
  119. }
  120. [Fact]
  121. public void RequestHeartbeat_should_force_another_heartbeat()
  122. {
  123. SetupHeartbeatConnection();
  124. _subject.Initialize();
  125. SpinWait.SpinUntil(() => _subject.Description.State == ServerState.Connected, TimeSpan.FromSeconds(5)).Should().BeTrue();
  126. _capturedEvents.Clear();
  127. _subject.RequestHeartbeat();
  128. // the next requests down heartbeat connection will fail, so the state should
  129. // go back to disconnected
  130. SpinWait.SpinUntil(() => _subject.Description.State == ServerState.Disconnected, TimeSpan.FromSeconds(5)).Should().BeTrue();
  131. // when heart fails, we immediately attempt a second, hence the multiple events...
  132. _capturedEvents.Next().Should().BeOfType<ServerHeartbeatStartedEvent>();
  133. _capturedEvents.Next().Should().BeOfType<ServerHeartbeatFailedEvent>();
  134. _capturedEvents.Next().Should().BeOfType<ServerHeartbeatStartedEvent>();
  135. _capturedEvents.Next().Should().BeOfType<ServerHeartbeatFailedEvent>();
  136. _capturedEvents.Any().Should().BeFalse();
  137. }
  138. [Fact]
  139. public void Invalidate_should_do_everything_invalidate_is_supposed_to_do()
  140. {
  141. SetupHeartbeatConnection();
  142. _subject.Initialize();
  143. SpinWait.SpinUntil(() => _subject.Description.State == ServerState.Connected, TimeSpan.FromSeconds(5)).Should().BeTrue();
  144. _capturedEvents.Clear();
  145. _subject.Invalidate("Test");
  146. _subject.Description.Type.Should().Be(ServerType.Unknown);
  147. // the next requests down heartbeat connection will fail, so the state should
  148. // go back to disconnected
  149. SpinWait.SpinUntil(() => _subject.Description.State == ServerState.Disconnected, TimeSpan.FromSeconds(5)).Should().BeTrue();
  150. SpinWait.SpinUntil(() => _capturedEvents.Count >= 4, TimeSpan.FromSeconds(5)).Should().BeTrue();
  151. // when heart fails, we immediately attempt a second, hence the multiple events...
  152. _capturedEvents.Next().Should().BeOfType<ServerHeartbeatStartedEvent>();
  153. _capturedEvents.Next().Should().BeOfType<ServerHeartbeatFailedEvent>();
  154. _capturedEvents.Next().Should().BeOfType<ServerHeartbeatStartedEvent>();
  155. _capturedEvents.Next().Should().BeOfType<ServerHeartbeatFailedEvent>();
  156. _capturedEvents.Any().Should().BeFalse();
  157. }
  158. private void SetupHeartbeatConnection()
  159. {
  160. var isMasterReply = MessageHelper.BuildReply<RawBsonDocument>(
  161. RawBsonDocumentHelper.FromJson("{ ok: 1 }"));
  162. var buildInfoReply = MessageHelper.BuildReply<RawBsonDocument>(
  163. RawBsonDocumentHelper.FromJson("{ ok: 1, version: \"2.6.3\" }"));
  164. _connection.EnqueueReplyMessage(isMasterReply);
  165. _connection.EnqueueReplyMessage(buildInfoReply);
  166. }
  167. }
  168. }