ForwardedPortRemoteTest_Dispose_PortStarted_ChannelBound.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Globalization;
  5. using System.Net;
  6. using System.Threading;
  7. using Microsoft.VisualStudio.TestTools.UnitTesting;
  8. using Moq;
  9. using Renci.SshNet.Channels;
  10. using Renci.SshNet.Common;
  11. using Renci.SshNet.Messages.Connection;
  12. namespace Renci.SshNet.Tests.Classes
  13. {
  14. [TestClass]
  15. public class ForwardedPortRemoteTest_Dispose_PortStarted_ChannelBound
  16. {
  17. private Mock<ISession> _sessionMock;
  18. private Mock<IConnectionInfo> _connectionInfoMock;
  19. private Mock<IChannelForwardedTcpip> _channelMock;
  20. private IList<EventArgs> _closingRegister;
  21. private IList<ExceptionEventArgs> _exceptionRegister;
  22. private IPEndPoint _bindEndpoint;
  23. private IPEndPoint _remoteEndpoint;
  24. private TimeSpan _expectedElapsedTime;
  25. private TimeSpan _elapsedTimeOfStop;
  26. private uint _remoteChannelNumberWhileClosing;
  27. private uint _remoteWindowSizeWhileClosing;
  28. private uint _remotePacketSizeWhileClosing;
  29. private uint _remoteChannelNumberStarted;
  30. private uint _remoteWindowSizeStarted;
  31. private uint _remotePacketSizeStarted;
  32. private string _originatorAddress;
  33. private uint _originatorPort;
  34. protected ForwardedPortRemote ForwardedPort { get; private set; }
  35. [TestInitialize]
  36. public void Setup()
  37. {
  38. Arrange();
  39. var stopwatch = new Stopwatch();
  40. stopwatch.Start();
  41. Act();
  42. stopwatch.Stop();
  43. _elapsedTimeOfStop = stopwatch.Elapsed;
  44. }
  45. [TestCleanup]
  46. public void Cleanup()
  47. {
  48. if (ForwardedPort != null)
  49. {
  50. ForwardedPort.Dispose();
  51. ForwardedPort = null;
  52. }
  53. }
  54. protected void Arrange()
  55. {
  56. var random = new Random();
  57. _closingRegister = new List<EventArgs>();
  58. _exceptionRegister = new List<ExceptionEventArgs>();
  59. _bindEndpoint = new IPEndPoint(IPAddress.Any, random.Next(IPEndPoint.MinPort, IPEndPoint.MaxPort));
  60. _remoteEndpoint = new IPEndPoint(IPAddress.Parse("193.168.1.5"), random.Next(IPEndPoint.MinPort, IPEndPoint.MaxPort));
  61. _expectedElapsedTime = TimeSpan.FromMilliseconds(random.Next(100, 500));
  62. ForwardedPort = new ForwardedPortRemote(_bindEndpoint.Address, (uint)_bindEndpoint.Port, _remoteEndpoint.Address, (uint)_remoteEndpoint.Port);
  63. _remoteChannelNumberWhileClosing = (uint) random.Next(0, 1000);
  64. _remoteWindowSizeWhileClosing = (uint) random.Next(0, int.MaxValue);
  65. _remotePacketSizeWhileClosing = (uint) random.Next(0, int.MaxValue);
  66. _remoteChannelNumberStarted = (uint)random.Next(0, 1000);
  67. _remoteWindowSizeStarted = (uint)random.Next(0, int.MaxValue);
  68. _remotePacketSizeStarted = (uint)random.Next(0, int.MaxValue);
  69. _originatorAddress = random.Next().ToString(CultureInfo.InvariantCulture);
  70. _originatorPort = (uint)random.Next(0, int.MaxValue);
  71. _connectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
  72. _sessionMock = new Mock<ISession>(MockBehavior.Strict);
  73. _channelMock = new Mock<IChannelForwardedTcpip>(MockBehavior.Strict);
  74. _connectionInfoMock.Setup(p => p.Timeout).Returns(TimeSpan.FromSeconds(15));
  75. _sessionMock.Setup(p => p.IsConnected).Returns(true);
  76. _sessionMock.Setup(p => p.ConnectionInfo).Returns(_connectionInfoMock.Object);
  77. _sessionMock.Setup(p => p.RegisterMessage("SSH_MSG_REQUEST_FAILURE"));
  78. _sessionMock.Setup(p => p.RegisterMessage("SSH_MSG_REQUEST_SUCCESS"));
  79. _sessionMock.Setup(p => p.RegisterMessage("SSH_MSG_CHANNEL_OPEN"));
  80. _sessionMock.Setup(
  81. p =>
  82. p.SendMessage(
  83. It.Is<GlobalRequestMessage>(
  84. g =>
  85. g.RequestName == GlobalRequestName.TcpIpForward &&
  86. g.AddressToBind == ForwardedPort.BoundHost &&
  87. g.PortToBind == ForwardedPort.BoundPort)))
  88. .Callback(
  89. () =>
  90. _sessionMock.Raise(s => s.RequestSuccessReceived += null,
  91. new MessageEventArgs<RequestSuccessMessage>(new RequestSuccessMessage())));
  92. _sessionMock.Setup(p => p.WaitOnHandle(It.IsAny<WaitHandle>()));
  93. _sessionMock.Setup(p => p.SendMessage(It.Is<ChannelOpenFailureMessage>(c => c.LocalChannelNumber == _remoteChannelNumberWhileClosing && c.ReasonCode == ChannelOpenFailureMessage.AdministrativelyProhibited && c.Description == string.Empty && c.Language == null)));
  94. _sessionMock.Setup(p => p.CreateChannelForwardedTcpip(_remoteChannelNumberStarted, _remoteWindowSizeStarted, _remotePacketSizeStarted)).Returns(_channelMock.Object);
  95. _channelMock.Setup(
  96. p =>
  97. p.Bind(
  98. It.Is<IPEndPoint>(
  99. ep => ep.Address.Equals(_remoteEndpoint.Address) && ep.Port == _remoteEndpoint.Port),
  100. ForwardedPort)).Callback(() => Thread.Sleep(_expectedElapsedTime));
  101. _channelMock.Setup(p => p.Close());
  102. _channelMock.Setup(p => p.Dispose());
  103. _sessionMock.Setup(
  104. p =>
  105. p.SendMessage(
  106. It.Is<GlobalRequestMessage>(
  107. g =>
  108. g.RequestName == GlobalRequestName.CancelTcpIpForward &&
  109. g.AddressToBind == ForwardedPort.BoundHost && g.PortToBind == ForwardedPort.BoundPort)));
  110. _sessionMock.Setup(p => p.MessageListenerCompleted).Returns(new ManualResetEvent(true));
  111. ForwardedPort.Closing += (sender, args) =>
  112. {
  113. _closingRegister.Add(args);
  114. _sessionMock.Raise(p => p.ChannelOpenReceived += null, new MessageEventArgs<ChannelOpenMessage>(new ChannelOpenMessage(_remoteChannelNumberWhileClosing, _remoteWindowSizeWhileClosing, _remotePacketSizeWhileClosing, new ForwardedTcpipChannelInfo(ForwardedPort.BoundHost, ForwardedPort.BoundPort, _originatorAddress, _originatorPort))));
  115. };
  116. ForwardedPort.Exception += (sender, args) => _exceptionRegister.Add(args);
  117. ForwardedPort.Session = _sessionMock.Object;
  118. ForwardedPort.Start();
  119. _sessionMock.Raise(p => p.ChannelOpenReceived += null, new MessageEventArgs<ChannelOpenMessage>(new ChannelOpenMessage(_remoteChannelNumberStarted, _remoteWindowSizeStarted, _remotePacketSizeStarted, new ForwardedTcpipChannelInfo(ForwardedPort.BoundHost, ForwardedPort.BoundPort, _originatorAddress, _originatorPort))));
  120. }
  121. protected virtual void Act()
  122. {
  123. ForwardedPort.Dispose();
  124. }
  125. [TestMethod]
  126. public void StopShouldBlockUntilBoundChannelHasClosed()
  127. {
  128. Assert.IsTrue(_elapsedTimeOfStop >= _expectedElapsedTime, string.Format("Expected {0} or greater but was {1}.", _expectedElapsedTime.TotalMilliseconds, _elapsedTimeOfStop.TotalMilliseconds));
  129. Assert.IsTrue(_elapsedTimeOfStop < _expectedElapsedTime.Add(TimeSpan.FromMilliseconds(200)));
  130. }
  131. [TestMethod]
  132. public void IsStartedShouldReturnFalse()
  133. {
  134. Assert.IsFalse(ForwardedPort.IsStarted);
  135. }
  136. [TestMethod]
  137. public void ForwardedPortShouldRejectChannelOpenMessagesThatAreReceivedWhileTheSuccessMessageForTheCancelOfTheForwardedPortIsNotReceived()
  138. {
  139. _sessionMock.Verify(p => p.SendMessage(new ChannelOpenFailureMessage(_remoteChannelNumberWhileClosing, string.Empty,
  140. ChannelOpenFailureMessage.AdministrativelyProhibited)), Times.Never);
  141. }
  142. [TestMethod]
  143. public void ForwardedPortShouldIgnoreChannelOpenMessagesWhenDisposed()
  144. {
  145. var channelNumberDisposed = (uint)new Random().Next(1001, int.MaxValue);
  146. var initialWindowSizeDisposed = (uint)new Random().Next(0, int.MaxValue);
  147. var maximumPacketSizeDisposed = (uint)new Random().Next(0, int.MaxValue);
  148. var originatorAddressDisposed = new Random().Next().ToString(CultureInfo.InvariantCulture);
  149. var originatorPortDisposed = (uint)new Random().Next(0, int.MaxValue);
  150. var channelMock = new Mock<IChannelForwardedTcpip>(MockBehavior.Strict);
  151. _sessionMock.Setup(
  152. p =>
  153. p.CreateChannelForwardedTcpip(channelNumberDisposed, initialWindowSizeDisposed, maximumPacketSizeDisposed)).Returns(channelMock.Object);
  154. _sessionMock.Setup(
  155. p =>
  156. p.SendMessage(new ChannelOpenFailureMessage(channelNumberDisposed, string.Empty,
  157. ChannelOpenFailureMessage.AdministrativelyProhibited)));
  158. _sessionMock.Raise(p => p.ChannelOpenReceived += null,
  159. new MessageEventArgs<ChannelOpenMessage>(new ChannelOpenMessage(channelNumberDisposed,
  160. initialWindowSizeDisposed, maximumPacketSizeDisposed,
  161. new ForwardedTcpipChannelInfo(ForwardedPort.BoundHost, ForwardedPort.BoundPort,
  162. originatorAddressDisposed, originatorPortDisposed))));
  163. _sessionMock.Verify(p => p.CreateChannelForwardedTcpip(channelNumberDisposed, initialWindowSizeDisposed, maximumPacketSizeDisposed), Times.Never);
  164. _sessionMock.Verify(p => p.SendMessage(It.Is<ChannelOpenFailureMessage>(c => c.LocalChannelNumber == channelNumberDisposed && c.ReasonCode == ChannelOpenFailureMessage.AdministrativelyProhibited && c.Description == string.Empty && c.Language == null)), Times.Never);
  165. }
  166. [TestMethod]
  167. public void ClosingShouldHaveFiredOnce()
  168. {
  169. Assert.AreEqual(1, _closingRegister.Count);
  170. }
  171. [TestMethod]
  172. public void ExceptionShouldNotHaveFired()
  173. {
  174. Assert.AreEqual(0, _exceptionRegister.Count);
  175. }
  176. [TestMethod]
  177. public void BindOnChannelShouldBeInvokedOnceForChannelOpenedWhileStarted()
  178. {
  179. _channelMock.Verify(
  180. c =>
  181. c.Bind(
  182. It.Is<IPEndPoint>(
  183. ep => ep.Address.Equals(_remoteEndpoint.Address) && ep.Port == _remoteEndpoint.Port),
  184. ForwardedPort), Times.Once);
  185. }
  186. [TestMethod]
  187. public void CloseOnChannelShouldBeInvokedOnce()
  188. {
  189. _channelMock.Verify(p => p.Close(), Times.Once);
  190. }
  191. [TestMethod]
  192. public void DisposeOnChannelShouldBeInvokedOnce()
  193. {
  194. _channelMock.Verify(p => p.Dispose(), Times.Once);
  195. }
  196. }
  197. }