PageRenderTime 28ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/MongoDB.Driver.Core.Tests/Core/Connections/TcpStreamFactoryTests.cs

http://github.com/mongodb/mongo-csharp-driver
C# | 257 lines | 209 code | 33 blank | 15 comment | 7 complexity | 79804c089171dc2608533f85571171a1 MD5 | raw file
Possible License(s): Apache-2.0
  1. /* Copyright 2013-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, 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.Net;
  17. using System.Net.Sockets;
  18. using System.Threading;
  19. using FluentAssertions;
  20. using MongoDB.Driver.Core.Configuration;
  21. using Xunit;
  22. using System.Threading.Tasks;
  23. using System.Reflection;
  24. using System.IO;
  25. using MongoDB.Bson.TestHelpers.XunitExtensions;
  26. using MongoDB.Driver.Core.TestHelpers.XunitExtensions;
  27. using MongoDB.Bson.TestHelpers;
  28. namespace MongoDB.Driver.Core.Connections
  29. {
  30. public class TcpStreamFactoryTests
  31. {
  32. [Theory]
  33. [ParameterAttributeData]
  34. public void Connect_should_dispose_socket_if_socket_fails([Values(false, true)] bool async)
  35. {
  36. RequireServer.Check();
  37. var subject = new TcpStreamFactory();
  38. var endpoint = new DnsEndPoint("test", 80); // not existed endpoint which will fail when we call socket.Connect
  39. using (var testSocket = new TestSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
  40. {
  41. Exception exception;
  42. if (async)
  43. {
  44. exception = Record.Exception(
  45. () =>
  46. subject
  47. .ConnectAsync(testSocket, endpoint, CancellationToken.None)
  48. .GetAwaiter()
  49. .GetResult());
  50. }
  51. else
  52. {
  53. exception = Record.Exception(() => subject.Connect(testSocket, endpoint, CancellationToken.None));
  54. }
  55. exception.Should().NotBeNull();
  56. testSocket.DisposeAttempts.Should().Be(1);
  57. }
  58. }
  59. [Fact]
  60. public void Constructor_should_throw_an_ArgumentNullException_when_tcpStreamSettings_is_null()
  61. {
  62. Action act = () => new TcpStreamFactory(null);
  63. act.ShouldThrow<ArgumentNullException>();
  64. }
  65. [Theory]
  66. [ParameterAttributeData]
  67. public void CreateStream_should_throw_a_SocketException_when_the_endpoint_could_not_be_resolved(
  68. [Values(false, true)]
  69. bool async)
  70. {
  71. var subject = new TcpStreamFactory();
  72. Action act;
  73. if (async)
  74. {
  75. act = () => subject.CreateStreamAsync(new DnsEndPoint("not-gonna-exist-i-hope", 27017), CancellationToken.None).GetAwaiter().GetResult();
  76. }
  77. else
  78. {
  79. act = () => subject.CreateStream(new DnsEndPoint("not-gonna-exist-i-hope", 27017), CancellationToken.None);
  80. }
  81. act.ShouldThrow<SocketException>();
  82. }
  83. [Theory]
  84. [ParameterAttributeData]
  85. public void CreateStream_should_throw_when_cancellation_is_requested(
  86. [Values(false, true)]
  87. bool async)
  88. {
  89. var subject = new TcpStreamFactory();
  90. var endPoint = new IPEndPoint(new IPAddress(0x01010101), 12345); // a non-existent host and port
  91. var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMilliseconds(20));
  92. Action action;
  93. if (async)
  94. {
  95. action = () => subject.CreateStreamAsync(endPoint, cancellationTokenSource.Token).GetAwaiter().GetResult();
  96. }
  97. else
  98. {
  99. action = () => subject.CreateStream(endPoint, cancellationTokenSource.Token);
  100. }
  101. action.ShouldThrow<OperationCanceledException>();
  102. }
  103. [Theory]
  104. [ParameterAttributeData]
  105. public void CreateStream_should_throw_when_connect_timeout_has_expired(
  106. [Values(false, true)]
  107. bool async)
  108. {
  109. var settings = new TcpStreamSettings(connectTimeout: TimeSpan.FromMilliseconds(20));
  110. var subject = new TcpStreamFactory(settings);
  111. var endPoint = new IPEndPoint(new IPAddress(0x01010101), 12345); // a non-existent host and port
  112. Action action;
  113. if (async)
  114. {
  115. action = () => subject.CreateStreamAsync(endPoint, CancellationToken.None).GetAwaiter().GetResult(); ;
  116. }
  117. else
  118. {
  119. action = () => subject.CreateStream(endPoint, CancellationToken.None);
  120. }
  121. action.ShouldThrow<TimeoutException>();
  122. }
  123. [SkippableTheory]
  124. [ParameterAttributeData]
  125. public void CreateStream_should_call_the_socketConfigurator(
  126. [Values(false, true)]
  127. bool async)
  128. {
  129. RequireServer.Check();
  130. var socketConfiguratorWasCalled = false;
  131. Action<Socket> socketConfigurator = s => socketConfiguratorWasCalled = true;
  132. var settings = new TcpStreamSettings(socketConfigurator: socketConfigurator);
  133. var subject = new TcpStreamFactory(settings);
  134. var endPoint = CoreTestConfiguration.ConnectionString.Hosts[0];
  135. if (async)
  136. {
  137. subject.CreateStreamAsync(endPoint, CancellationToken.None).GetAwaiter().GetResult();
  138. }
  139. else
  140. {
  141. subject.CreateStream(endPoint, CancellationToken.None);
  142. }
  143. socketConfiguratorWasCalled.Should().BeTrue();
  144. }
  145. [SkippableTheory]
  146. [ParameterAttributeData]
  147. public void CreateStream_should_connect_to_a_running_server_and_return_a_non_null_stream(
  148. [Values(false, true)]
  149. bool async)
  150. {
  151. RequireServer.Check();
  152. var subject = new TcpStreamFactory();
  153. var endPoint = CoreTestConfiguration.ConnectionString.Hosts[0];
  154. Stream stream;
  155. if (async)
  156. {
  157. stream = subject.CreateStreamAsync(endPoint, CancellationToken.None).GetAwaiter().GetResult();
  158. }
  159. else
  160. {
  161. stream = subject.CreateStream(endPoint, CancellationToken.None);
  162. }
  163. stream.Should().NotBeNull();
  164. }
  165. [SkippableTheory]
  166. [ParameterAttributeData]
  167. public void SocketConfigurator_can_be_used_to_set_keepAlive(
  168. [Values(false, true)]
  169. bool async)
  170. {
  171. RequireServer.Check();
  172. Action<Socket> socketConfigurator = s => s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
  173. var settings = new TcpStreamSettings(socketConfigurator: socketConfigurator);
  174. var subject = new TcpStreamFactory(settings);
  175. var endPoint = CoreTestConfiguration.ConnectionString.Hosts[0];
  176. Stream stream;
  177. if (async)
  178. {
  179. stream = subject.CreateStreamAsync(endPoint, CancellationToken.None).GetAwaiter().GetResult();
  180. }
  181. else
  182. {
  183. stream = subject.CreateStream(endPoint, CancellationToken.None);
  184. }
  185. var socketProperty = typeof(NetworkStream).GetProperty("Socket", BindingFlags.NonPublic | BindingFlags.Instance);
  186. var socket = (Socket)socketProperty.GetValue(stream);
  187. var keepAlive = (int)socket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive);
  188. keepAlive.Should().NotBe(0); // .NET returns 1 but Mono returns 8
  189. }
  190. // nested types
  191. private class TestSocket : Socket
  192. {
  193. public int DisposeAttempts { get; set; } = 0;
  194. public TestSocket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType) : base(addressFamily, socketType, protocolType)
  195. {
  196. }
  197. public TestSocket(SocketType socketType, ProtocolType protocolType) : base(socketType, protocolType)
  198. {
  199. }
  200. #if !NETCOREAPP1_1
  201. public TestSocket(SocketInformation socketInformation) : base(socketInformation)
  202. {
  203. }
  204. #endif
  205. protected override void Dispose(bool disposing)
  206. {
  207. base.Dispose(disposing);
  208. DisposeAttempts++;
  209. }
  210. }
  211. }
  212. internal static class TcpStreamFactoryReflector
  213. {
  214. internal static TcpStreamSettings _settings(this TcpStreamFactory obj) => (TcpStreamSettings)Reflector.GetFieldValue(obj, nameof(_settings));
  215. internal static void Connect(this TcpStreamFactory obj, Socket socket, EndPoint endPoint, CancellationToken cancellationToken)
  216. {
  217. Reflector.Invoke(obj, nameof(Connect), socket, endPoint, cancellationToken);
  218. }
  219. internal static Task ConnectAsync(this TcpStreamFactory obj, Socket socket, EndPoint endPoint, CancellationToken cancellationToken)
  220. {
  221. return (Task)Reflector.Invoke(obj, nameof(ConnectAsync), socket, endPoint, cancellationToken);
  222. }
  223. }
  224. }