ChannelForwardedTcpipTest_Dispose_SessionIsConnectedAndChannelIsOpen.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Net;
  4. using System.Net.Sockets;
  5. using System.Threading;
  6. using Microsoft.VisualStudio.TestTools.UnitTesting;
  7. using Moq;
  8. using Renci.SshNet.Channels;
  9. using Renci.SshNet.Messages.Connection;
  10. using Renci.SshNet.Tests.Common;
  11. namespace Renci.SshNet.Tests.Classes.Channels
  12. {
  13. [TestClass]
  14. public class ChannelForwardedTcpipTest_Dispose_SessionIsConnectedAndChannelIsOpen
  15. {
  16. private Mock<ISession> _sessionMock;
  17. private Mock<IForwardedPort> _forwardedPortMock;
  18. private Mock<IConnectionInfo> _connectionInfoMock;
  19. private ChannelForwardedTcpip _channel;
  20. private uint _localChannelNumber;
  21. private uint _localWindowSize;
  22. private uint _localPacketSize;
  23. private uint _remoteWindowSize;
  24. private uint _remotePacketSize;
  25. private uint _remoteChannelNumber;
  26. private TimeSpan _channelCloseTimeout;
  27. private IPEndPoint _remoteEndpoint;
  28. private AsyncSocketListener _remoteListener;
  29. private Exception _channelException;
  30. private IList<Socket> _connectedRegister;
  31. private IList<Socket> _disconnectedRegister;
  32. private Thread _channelThread;
  33. private TimeSpan _connectionInfoTimeout;
  34. [TestInitialize]
  35. public void Initialize()
  36. {
  37. Arrange();
  38. Act();
  39. }
  40. [TestCleanup]
  41. public void CleanUp()
  42. {
  43. if (_remoteListener != null)
  44. {
  45. _remoteListener.Stop();
  46. _remoteListener = null;
  47. }
  48. if (_channelThread != null)
  49. {
  50. _channelThread.Join();
  51. _channelThread = null;
  52. }
  53. if (_channel != null)
  54. {
  55. _channel.Dispose();
  56. _channel = null;
  57. }
  58. }
  59. private void Arrange()
  60. {
  61. var random = new Random();
  62. _localChannelNumber = (uint)random.Next(0, int.MaxValue);
  63. _localWindowSize = (uint)random.Next(2000, 3000);
  64. _localPacketSize = (uint)random.Next(1000, 2000);
  65. _remoteChannelNumber = (uint)random.Next(0, int.MaxValue);
  66. _remoteWindowSize = (uint)random.Next(0, int.MaxValue);
  67. _remotePacketSize = (uint)random.Next(100, 200);
  68. _channelCloseTimeout = TimeSpan.FromSeconds(random.Next(10, 20));
  69. _channelException = null;
  70. _connectedRegister = new List<Socket>();
  71. _disconnectedRegister = new List<Socket>();
  72. _connectionInfoTimeout = TimeSpan.FromSeconds(5);
  73. _remoteEndpoint = new IPEndPoint(IPAddress.Loopback, 8122);
  74. _sessionMock = new Mock<ISession>(MockBehavior.Strict);
  75. _connectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
  76. _forwardedPortMock = new Mock<IForwardedPort>(MockBehavior.Strict);
  77. var sequence = new MockSequence();
  78. _ = _sessionMock.InSequence(sequence)
  79. .Setup(p => p.IsConnected)
  80. .Returns(true);
  81. _ = _sessionMock.InSequence(sequence)
  82. .Setup(p => p.ConnectionInfo)
  83. .Returns(_connectionInfoMock.Object);
  84. _ = _connectionInfoMock.InSequence(sequence)
  85. .Setup(p => p.Timeout)
  86. .Returns(_connectionInfoTimeout);
  87. _ = _sessionMock.InSequence(sequence)
  88. .Setup(p => p.SendMessage(It.Is<ChannelOpenConfirmationMessage>(m =>
  89. m.LocalChannelNumber == _remoteChannelNumber &&
  90. m.InitialWindowSize == _localWindowSize &&
  91. m.MaximumPacketSize == _localPacketSize &&
  92. m.RemoteChannelNumber == _localChannelNumber)));
  93. _ = _sessionMock.InSequence(sequence)
  94. .Setup(p => p.IsConnected)
  95. .Returns(true);
  96. _ = _sessionMock.InSequence(sequence)
  97. .Setup(p => p.TrySendMessage(It.Is<ChannelEofMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)))
  98. .Returns(true);
  99. _ = _sessionMock.InSequence(sequence)
  100. .Setup(p => p.IsConnected)
  101. .Returns(true);
  102. _ = _sessionMock.InSequence(sequence)
  103. .Setup(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)))
  104. .Returns(true);
  105. _ = _sessionMock.InSequence(sequence)
  106. .Setup(p => p.ConnectionInfo)
  107. .Returns(_connectionInfoMock.Object);
  108. _ = _connectionInfoMock.InSequence(sequence)
  109. .Setup(p => p.ChannelCloseTimeout)
  110. .Returns(_channelCloseTimeout);
  111. _ = _sessionMock.InSequence(sequence)
  112. .Setup(p => p.TryWait(It.IsAny<EventWaitHandle>(), _channelCloseTimeout))
  113. .Callback<WaitHandle, TimeSpan>((waitHandle, channelCloseTimeout) =>
  114. {
  115. _sessionMock.Raise(
  116. s => s.ChannelCloseReceived += null,
  117. new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
  118. _ = waitHandle.WaitOne();
  119. })
  120. .Returns(WaitResult.Success);
  121. _remoteListener = new AsyncSocketListener(_remoteEndpoint);
  122. _remoteListener.Connected += _connectedRegister.Add;
  123. _remoteListener.Disconnected += _disconnectedRegister.Add;
  124. _remoteListener.Start();
  125. _channel = new ChannelForwardedTcpip(_sessionMock.Object,
  126. _localChannelNumber,
  127. _localWindowSize,
  128. _localPacketSize,
  129. _remoteChannelNumber,
  130. _remoteWindowSize,
  131. _remotePacketSize);
  132. _channelThread = new Thread(() =>
  133. {
  134. try
  135. {
  136. _channel.Bind(_remoteEndpoint, _forwardedPortMock.Object);
  137. }
  138. catch (Exception ex)
  139. {
  140. _channelException = ex;
  141. }
  142. });
  143. _channelThread.Start();
  144. // give channel time to bind to remote endpoint
  145. Thread.Sleep(300);
  146. }
  147. private void Act()
  148. {
  149. _channel.Dispose();
  150. Assert.IsTrue(_channelThread.Join(TimeSpan.FromSeconds(1)));
  151. }
  152. [TestMethod]
  153. public void ChannelShouldShutdownSocketToRemoteListener()
  154. {
  155. Assert.AreEqual(1, _connectedRegister.Count);
  156. Assert.AreEqual(1, _disconnectedRegister.Count);
  157. Assert.AreSame(_connectedRegister[0], _disconnectedRegister[0]);
  158. }
  159. [TestMethod]
  160. public void BindShouldHaveFinishedWithoutException()
  161. {
  162. Assert.IsNull(_channelException, _channelException?.ToString());
  163. }
  164. [TestMethod]
  165. public void ChannelEofMessageShouldBeSentOnce()
  166. {
  167. _sessionMock.Verify(p => p.TrySendMessage(It.Is<ChannelEofMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)), Times.Once);
  168. }
  169. [TestMethod]
  170. public void ChannelCloseMessageShouldBeSentOnce()
  171. {
  172. _sessionMock.Verify(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)), Times.Once);
  173. }
  174. [TestMethod]
  175. public void IsOpenShouldReturnFalse()
  176. {
  177. Assert.IsFalse(_channel.IsOpen);
  178. }
  179. }
  180. }