PageRenderTime 51ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/src/MongoDB.Driver.Core.Tests/Core/Servers/ServerTests.cs

http://github.com/mongodb/mongo-csharp-driver
C# | 260 lines | 186 code | 54 blank | 20 comment | 8 complexity | d77cb969b3f52e12374deb80d5d2b792 MD5 | raw file
Possible License(s): Apache-2.0
  1. /* Copyright 2013-2014 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, 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.Linq;
  18. using System.Net;
  19. using System.Text;
  20. using System.Threading;
  21. using System.Threading.Tasks;
  22. using FluentAssertions;
  23. using MongoDB.Bson;
  24. using MongoDB.Driver.Core.Clusters;
  25. using MongoDB.Driver.Core.Configuration;
  26. using MongoDB.Driver.Core.ConnectionPools;
  27. using MongoDB.Driver.Core.Connections;
  28. using MongoDB.Driver.Core.Events;
  29. using MongoDB.Driver.Core.Servers;
  30. using MongoDB.Driver.Core.Helpers;
  31. using NSubstitute;
  32. using NUnit.Framework;
  33. namespace MongoDB.Driver.Core.Servers
  34. {
  35. [TestFixture]
  36. public class ServerTests
  37. {
  38. private ClusterId _clusterId;
  39. private ClusterConnectionMode _clusterConnectionMode;
  40. private IConnectionPool _connectionPool;
  41. private IConnectionPoolFactory _connectionPoolFactory;
  42. private EndPoint _endPoint;
  43. private MockConnection _heartbeatConnection;
  44. private IConnectionFactory _heartbeatConnectionFactory;
  45. private IServerListener _listener;
  46. private ServerSettings _settings;
  47. private ClusterableServer _subject;
  48. [SetUp]
  49. public void Setup()
  50. {
  51. _clusterId = new ClusterId();
  52. _clusterConnectionMode = ClusterConnectionMode.Standalone;
  53. _connectionPool = Substitute.For<IConnectionPool>();
  54. _connectionPoolFactory = Substitute.For<IConnectionPoolFactory>();
  55. _connectionPoolFactory.CreateConnectionPool(null, null)
  56. .ReturnsForAnyArgs(_connectionPool);
  57. _endPoint = new DnsEndPoint("localhost", 27017);
  58. _heartbeatConnection = new MockConnection();
  59. _heartbeatConnectionFactory = Substitute.For<IConnectionFactory>();
  60. _heartbeatConnectionFactory.CreateConnection(null, null)
  61. .ReturnsForAnyArgs(_heartbeatConnection);
  62. _listener = Substitute.For<IServerListener>();
  63. _settings = new ServerSettings(heartbeatInterval: Timeout.InfiniteTimeSpan);
  64. _subject = new ClusterableServer(_clusterId, _clusterConnectionMode, _settings, _endPoint, _connectionPoolFactory, _heartbeatConnectionFactory, _listener);
  65. }
  66. [Test]
  67. public void Constructor_should_throw_when_settings_is_null()
  68. {
  69. Action act = () => new ClusterableServer(_clusterId, _clusterConnectionMode, null, _endPoint, _connectionPoolFactory, _heartbeatConnectionFactory, _listener);
  70. act.ShouldThrow<ArgumentNullException>();
  71. }
  72. [Test]
  73. public void Constructor_should_throw_when_clusterId_is_null()
  74. {
  75. Action act = () => new ClusterableServer(null, _clusterConnectionMode, _settings, _endPoint, _connectionPoolFactory, _heartbeatConnectionFactory, _listener);
  76. act.ShouldThrow<ArgumentNullException>();
  77. }
  78. [Test]
  79. public void Constructor_should_throw_when_endPoint_is_null()
  80. {
  81. Action act = () => new ClusterableServer(_clusterId, _clusterConnectionMode, _settings, null, _connectionPoolFactory, _heartbeatConnectionFactory, _listener);
  82. act.ShouldThrow<ArgumentNullException>();
  83. }
  84. [Test]
  85. public void Constructor_should_throw_when_connectionPoolFactory_is_null()
  86. {
  87. Action act = () => new ClusterableServer(_clusterId, _clusterConnectionMode, _settings, _endPoint, null, _heartbeatConnectionFactory, _listener);
  88. act.ShouldThrow<ArgumentNullException>();
  89. }
  90. [Test]
  91. public void Constructor_should_throw_when_heartbeatConnectionFactory_is_null()
  92. {
  93. Action act = () => new ClusterableServer(_clusterId, _clusterConnectionMode, _settings, _endPoint, _connectionPoolFactory, null, _listener);
  94. act.ShouldThrow<ArgumentNullException>();
  95. }
  96. [Test]
  97. public void Constructor_should_not_throw_when_listener_is_null()
  98. {
  99. Action act = () => new ClusterableServer(_clusterId, _clusterConnectionMode, _settings, _endPoint, _connectionPoolFactory, _heartbeatConnectionFactory, null);
  100. act.ShouldNotThrow();
  101. }
  102. [Test]
  103. public void Description_should_return_default_when_uninitialized()
  104. {
  105. var description = _subject.Description;
  106. description.EndPoint.Should().Be(_endPoint);
  107. description.Type.Should().Be(ServerType.Unknown);
  108. description.State.Should().Be(ServerState.Disconnected);
  109. }
  110. [Test]
  111. public void Description_should_return_default_when_disposed()
  112. {
  113. _subject.Dispose();
  114. var description = _subject.Description;
  115. description.EndPoint.Should().Be(_endPoint);
  116. description.Type.Should().Be(ServerType.Unknown);
  117. description.State.Should().Be(ServerState.Disconnected);
  118. }
  119. [Test]
  120. public void DescriptionChanged_should_be_raised_when_moving_from_disconnected_to_connected()
  121. {
  122. var changes = new List<ServerDescriptionChangedEventArgs>();
  123. _subject.DescriptionChanged += (o, e) => changes.Add(e);
  124. SetupHeartbeatConnection();
  125. _subject.Initialize();
  126. SpinWait.SpinUntil(() => _subject.Description.State == ServerState.Connected, TimeSpan.FromSeconds(4));
  127. changes.Count.Should().Be(1);
  128. changes[0].OldServerDescription.State.Should().Be(ServerState.Disconnected);
  129. changes[0].NewServerDescription.State.Should().Be(ServerState.Connected);
  130. }
  131. [Test]
  132. public void Description_should_be_connected_after_successful_heartbeat()
  133. {
  134. SetupHeartbeatConnection();
  135. _subject.Initialize();
  136. SpinWait.SpinUntil(() => _subject.Description.State == ServerState.Connected, TimeSpan.FromSeconds(4));
  137. _subject.Description.State.Should().Be(ServerState.Connected);
  138. _subject.Description.Type.Should().Be(ServerType.Standalone);
  139. }
  140. [Test]
  141. public void GetChannelAsync_should_throw_when_not_initialized()
  142. {
  143. Action act = () => _subject.GetChannelAsync(CancellationToken.None).Wait();
  144. act.ShouldThrow<InvalidOperationException>();
  145. }
  146. [Test]
  147. public void GetChannelAsync_should_throw_when_disposed()
  148. {
  149. _subject.Dispose();
  150. Action act = () => _subject.GetChannelAsync(CancellationToken.None).Wait();
  151. act.ShouldThrow<ObjectDisposedException>();
  152. }
  153. [Test]
  154. public void GetChannelAsync_should_get_a_connection()
  155. {
  156. _subject.Initialize();
  157. var channel = _subject.GetChannelAsync(CancellationToken.None).Result;
  158. channel.Should().NotBeNull();
  159. }
  160. [Test]
  161. public void RequestHeartbeat_should_force_another_heartbeat()
  162. {
  163. SetupHeartbeatConnection();
  164. _subject.Initialize();
  165. SpinWait.SpinUntil(() => _subject.Description.State == ServerState.Connected, TimeSpan.FromSeconds(4));
  166. _subject.RequestHeartbeat();
  167. // the next requests down heartbeat connection will fail, so the state should
  168. // go back to disconnected
  169. SpinWait.SpinUntil(() => _subject.Description.State == ServerState.Disconnected, TimeSpan.FromSeconds(4));
  170. }
  171. [Test]
  172. public void Invalidate_should_do_everything_invalidate_is_supposed_to_do()
  173. {
  174. SetupHeartbeatConnection();
  175. _subject.Initialize();
  176. SpinWait.SpinUntil(() => _subject.Description.State == ServerState.Connected, TimeSpan.FromSeconds(4));
  177. _subject.Invalidate();
  178. _connectionPool.Received().Clear();
  179. _subject.Description.Type.Should().Be(ServerType.Unknown);
  180. // the next requests down heartbeat connection will fail, so the state should
  181. // go back to disconnected
  182. SpinWait.SpinUntil(() => _subject.Description.State == ServerState.Disconnected, TimeSpan.FromSeconds(4));
  183. }
  184. [Test]
  185. public void A_failed_heartbeat_should_clear_the_connection_pool()
  186. {
  187. SetupHeartbeatConnection();
  188. _subject.Initialize();
  189. SpinWait.SpinUntil(() => _subject.Description.State == ServerState.Connected, TimeSpan.FromSeconds(4));
  190. _subject.RequestHeartbeat();
  191. // the next requests down heartbeat connection will fail, so the state should
  192. // go back to disconnected
  193. SpinWait.SpinUntil(() => _subject.Description.State == ServerState.Disconnected, TimeSpan.FromSeconds(4));
  194. _connectionPool.ReceivedWithAnyArgs().Clear();
  195. }
  196. private void SetupHeartbeatConnection()
  197. {
  198. var isMasterReply = MessageHelper.BuildSuccessReply<RawBsonDocument>(
  199. RawBsonDocumentHelper.FromJson("{ ok: 1 }"));
  200. var buildInfoReply = MessageHelper.BuildSuccessReply<RawBsonDocument>(
  201. RawBsonDocumentHelper.FromJson("{ ok: 1, version: \"2.6.3\" }"));
  202. _heartbeatConnection.EnqueueReplyMessage(isMasterReply);
  203. _heartbeatConnection.EnqueueReplyMessage(buildInfoReply);
  204. }
  205. }
  206. }