Parcourir la source

* Add TryWait overloads to (I)Session that return the result of the wait instead of throwing an exception.
* Introduce a ChannelCloseTimeout property on ConnectionInfo that allows you to control how long you want to wait for the server to send a SSH_MSG_CHANNEL_CLOSE. The default value is 1 second.
* Use the newly introduced TryWait on Session with ChannelCloseTimeout as timeout in Channel to avoid throwing an exception when the server does not send a SSH_MSG_CHANNEL_CLOSE.
Fixes #335.
* Removed unused WaitHandle from Channel.

Gert Driesen il y a 8 ans
Parent
commit
3e304ea7e7
61 fichiers modifiés avec 2554 ajouts et 1696 suppressions
  1. 104 75
      src/Renci.SshNet.Tests/Classes/Channels/ChannelDirectTcpipTest.cs
  2. 21 16
      src/Renci.SshNet.Tests/Classes/Channels/ChannelDirectTcpipTest_Dispose_SessionIsConnectedAndChannelIsOpen.cs
  3. 9 5
      src/Renci.SshNet.Tests/Classes/Channels/ChannelForwardedTcpipTest_Dispose_SessionIsConnectedAndChannelIsOpen.cs
  4. 37 0
      src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTestBase.cs
  5. 41 38
      src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Dispose_Disposed.cs
  6. 39 36
      src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_ChannelCloseAndChannelEofReceived_DisposeInEventHandler.cs
  7. 55 57
      src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_ChannelCloseAndChannelEofReceived_SendChannelCloseMessageFailure.cs
  8. 57 55
      src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_ChannelCloseAndChannelEofReceived_SendChannelCloseMessageSuccess.cs
  9. 54 56
      src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_ChannelCloseReceived_SendChannelCloseMessageFailure.cs
  10. 31 29
      src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_ChannelCloseReceived_SendChannelCloseMessageSuccess.cs
  11. 53 56
      src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_ChannelEofReceived_SendChannelCloseMessageFailure.cs
  12. 38 36
      src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_ChannelEofReceived_SendChannelCloseMessageSuccess.cs
  13. 74 71
      src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_NoChannelCloseOrChannelEofReceived.cs
  14. 73 71
      src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_NoChannelCloseOrChannelEofReceived_SendChannelEofMessageFailure.cs
  15. 51 53
      src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Dispose_SessionIsNotConnectedAndChannelIsOpen_ChannelCloseAndChannelEofReceived.cs
  16. 50 52
      src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Dispose_SessionIsNotConnectedAndChannelIsOpen_ChannelCloseReceived.cs
  17. 48 51
      src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Dispose_SessionIsNotConnectedAndChannelIsOpen_NoChannelCloseOrChannelEofReceived.cs
  18. 31 28
      src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_OnSessionChannelCloseReceived_SessionIsConnectedAndChannelIsOpen.cs
  19. 34 35
      src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Open_ExceptionWaitingOnOpenConfirmation.cs
  20. 22 24
      src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Open_OnOpenFailureReceived_NoRetriesAvailable.cs
  21. 75 77
      src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Open_OnOpenFailureReceived_RetriesAvalable.cs
  22. 37 0
      src/Renci.SshNet.Tests/Classes/Channels/ChannelTestBase.cs
  23. 18 19
      src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_Dispose_SessionIsConnectedAndChannelIsNotOpen.cs
  24. 63 57
      src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_Dispose_SessionIsConnectedAndChannelIsOpen_EofNotReceived.cs
  25. 56 56
      src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_Dispose_SessionIsConnectedAndChannelIsOpen_EofNotReceived_SendEofInvoked.cs
  26. 48 57
      src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_Dispose_SessionIsConnectedAndChannelIsOpen_EofReceived.cs
  27. 27 47
      src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_Dispose_SessionIsConnectedAndChannelIsOpen_EofReceived_DisconnectWaitingForChannelCloseMessage.cs
  28. 30 66
      src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_Dispose_SessionIsConnectedAndChannelIsOpen_EofReceived_TimeoutWaitingForChannelCloseMessage.cs
  29. 16 17
      src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_Dispose_SessionIsNotConnectedAndChannelIsNotOpen.cs
  30. 18 19
      src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_Dispose_SessionIsNotConnectedAndChannelIsOpen.cs
  31. 14 14
      src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_OnSessionChannelCloseReceived_OnClose_Exception.cs
  32. 30 34
      src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_OnSessionChannelCloseReceived_SessionIsConnectedAndChannelIsOpen_DisposeChannelInClosedEventHandler.cs
  33. 34 30
      src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_OnSessionChannelCloseReceived_SessionIsConnectedAndChannelIsOpen_EofNotReceived.cs
  34. 43 41
      src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_OnSessionChannelCloseReceived_SessionIsConnectedAndChannelIsOpen_EofReceived.cs
  35. 18 18
      src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_OnSessionChannelDataReceived_OnData_Exception.cs
  36. 22 22
      src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_OnSessionChannelEofReceived_OnEof_Exception.cs
  37. 18 18
      src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_OnSessionChannelExtendedDataReceived_OnExtendedData_Exception.cs
  38. 19 19
      src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_OnSessionChannelFailureReceived_OnFailure_Exception.cs
  39. 20 20
      src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_OnSessionChannelRequestReceived_OnRequest_Exception.cs
  40. 19 19
      src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_OnSessionChannelSuccessReceived_OnSuccess_Exception.cs
  41. 21 21
      src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_OnSessionChannelWindowAdjustReceived_OnWindowAdjust_Exception.cs
  42. 17 17
      src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_OnSessionDisconnected_OnDisconnected_Exception.cs
  43. 21 22
      src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_OnSessionDisconnected_SessionIsConnectedAndChannelIsOpen.cs
  44. 17 18
      src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_OnSessionErrorOccurred_OnErrorOccurred_Exception.cs
  45. 18 18
      src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_SendEof_ChannelIsNotOpen.cs
  46. 21 22
      src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_SendEof_ChannelIsOpen.cs
  47. 90 4
      src/Renci.SshNet.Tests/Classes/SessionTest_Connected.cs
  48. 58 7
      src/Renci.SshNet.Tests/Classes/SessionTest_Connected_ConnectionReset.cs
  49. 48 4
      src/Renci.SshNet.Tests/Classes/SessionTest_Connected_Disconnect.cs
  50. 60 8
      src/Renci.SshNet.Tests/Classes/SessionTest_Connected_ServerSendsBadPacket.cs
  51. 64 9
      src/Renci.SshNet.Tests/Classes/SessionTest_Connected_ServerSendsDisconnectMessage.cs
  52. 35 6
      src/Renci.SshNet.Tests/Classes/SessionTest_Connected_ServerSendsDisconnectMessageAndShutsDownSocket.cs
  53. 236 0
      src/Renci.SshNet.Tests/Classes/SessionTest_Connected_ServerSendsUnsupportedMessageType.cs
  54. 45 2
      src/Renci.SshNet.Tests/Classes/SessionTest_Connected_ServerShutsDownSendAfterSendingIncompletePacket.cs
  55. 90 6
      src/Renci.SshNet.Tests/Classes/SessionTest_Connected_ServerShutsDownSocket.cs
  56. 53 11
      src/Renci.SshNet.Tests/Classes/SessionTest_NotConnected.cs
  57. 8 23
      src/Renci.SshNet/Channels/Channel.cs
  58. 30 1
      src/Renci.SshNet/ConnectionInfo.cs
  59. 12 0
      src/Renci.SshNet/IConnectionInfo.cs
  60. 4 0
      src/Renci.SshNet/ISession.cs
  61. 59 3
      src/Renci.SshNet/Session.cs

+ 104 - 75
src/Renci.SshNet.Tests/Classes/Channels/ChannelDirectTcpipTest.cs

@@ -27,6 +27,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private uint _remoteWindowSize;
         private uint _remotePacketSize;
         private uint _remoteChannelNumber;
+        private TimeSpan _channelCloseTimeout;
 
         protected override void OnInit()
         {
@@ -40,8 +41,9 @@ namespace Renci.SshNet.Tests.Classes.Channels
             _port = (uint) random.Next(IPEndPoint.MinPort, IPEndPoint.MaxPort);
             _localChannelNumber = (uint) random.Next(0, int.MaxValue);
             _remoteWindowSize = (uint) random.Next(0, int.MaxValue);
-            _remotePacketSize = (uint)random.Next(100, 200);
-            _remoteChannelNumber = (uint)random.Next(0, int.MaxValue);
+            _remotePacketSize = (uint) random.Next(100, 200);
+            _remoteChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _channelCloseTimeout = TimeSpan.FromSeconds(random.Next(10, 20));
 
             _sessionMock = new Mock<ISession>(MockBehavior.Strict);
             _forwardedPortMock = new Mock<IForwardedPort>(MockBehavior.Strict);
@@ -53,11 +55,14 @@ namespace Renci.SshNet.Tests.Classes.Channels
         {
             _sessionMock.Setup(p => p.IsConnected).Returns(true);
             _sessionMock.Setup(p => p.SendMessage(It.IsAny<ChannelOpenMessage>()))
-                .Callback<Message>(m => _sessionMock.Raise(p => p.ChannelOpenConfirmationReceived += null,
-                    new MessageEventArgs<ChannelOpenConfirmationMessage>(
-                        new ChannelOpenConfirmationMessage(((ChannelOpenMessage)m).LocalChannelNumber, _remoteWindowSize, _remotePacketSize, _remoteChannelNumber))));
+                        .Callback<Message>(m => _sessionMock.Raise(p => p.ChannelOpenConfirmationReceived += null,
+                                                                   new MessageEventArgs<ChannelOpenConfirmationMessage>(
+                                                                       new ChannelOpenConfirmationMessage(((ChannelOpenMessage) m).LocalChannelNumber,
+                                                                                                          _remoteWindowSize,
+                                                                                                          _remotePacketSize,
+                                                                                                          _remoteChannelNumber))));
             _sessionMock.Setup(p => p.WaitOnHandle(It.IsAny<EventWaitHandle>()))
-                .Callback<WaitHandle>(p => p.WaitOne(Session.Infinite));
+                        .Callback<WaitHandle>(p => p.WaitOne(Session.Infinite));
 
             var localPortEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
             using (var localPortListener = new AsyncSocketListener(localPortEndPoint))
@@ -65,25 +70,27 @@ namespace Renci.SshNet.Tests.Classes.Channels
                 localPortListener.Start();
 
                 localPortListener.Connected += socket =>
-                    {
-                        var channel = new ChannelDirectTcpip(_sessionMock.Object, _localChannelNumber, _localWindowSize,
-                            _localPacketSize);
-                        channel.Open(_remoteHost, _port, _forwardedPortMock.Object, socket);
-
-                        var closeForwardedPortThread =
-                            new Thread(() =>
-                                {
-                                    // sleep for a short period to allow channel to actually start receiving from socket
-                                    Thread.Sleep(100);
-                                    // raise Closing event on forwarded port
-                                    _forwardedPortMock.Raise(p => p.Closing += null, EventArgs.Empty);
-                                });
-                        closeForwardedPortThread.Start();
-
-                        channel.Bind();
-
-                        closeForwardedPortThread.Join();
-                    };
+                {
+                    var channel = new ChannelDirectTcpip(_sessionMock.Object,
+                                                         _localChannelNumber,
+                                                         _localWindowSize,
+                                                         _localPacketSize);
+                    channel.Open(_remoteHost, _port, _forwardedPortMock.Object, socket);
+
+                    var closeForwardedPortThread =
+                        new Thread(() =>
+                        {
+                            // sleep for a short period to allow channel to actually start receiving from socket
+                            Thread.Sleep(100);
+                            // raise Closing event on forwarded port
+                            _forwardedPortMock.Raise(p => p.Closing += null, EventArgs.Empty);
+                        });
+                    closeForwardedPortThread.Start();
+
+                    channel.Bind();
+
+                    closeForwardedPortThread.Join();
+                };
 
                 var client = new Socket(localPortEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                 client.Connect(localPortEndPoint);
@@ -103,11 +110,14 @@ namespace Renci.SshNet.Tests.Classes.Channels
         {
             _sessionMock.Setup(p => p.IsConnected).Returns(true);
             _sessionMock.Setup(p => p.SendMessage(It.IsAny<ChannelOpenMessage>()))
-                .Callback<Message>(m => _sessionMock.Raise(p => p.ChannelOpenConfirmationReceived += null,
-                    new MessageEventArgs<ChannelOpenConfirmationMessage>(
-                        new ChannelOpenConfirmationMessage(((ChannelOpenMessage)m).LocalChannelNumber, _remoteWindowSize, _remotePacketSize, _remoteChannelNumber))));
+                        .Callback<Message>(m => _sessionMock.Raise(p => p.ChannelOpenConfirmationReceived += null,
+                                                                   new MessageEventArgs<ChannelOpenConfirmationMessage>(
+                                                                       new ChannelOpenConfirmationMessage(((ChannelOpenMessage) m).LocalChannelNumber,
+                                                                                                          _remoteWindowSize,
+                                                                                                          _remotePacketSize,
+                                                                                                          _remoteChannelNumber))));
             _sessionMock.Setup(p => p.WaitOnHandle(It.IsAny<EventWaitHandle>()))
-                .Callback<WaitHandle>(p => p.WaitOne(Session.Infinite));
+                        .Callback<WaitHandle>(p => p.WaitOne(Session.Infinite));
 
             var localPortEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
             using (var localPortListener = new AsyncSocketListener(localPortEndPoint))
@@ -116,19 +126,21 @@ namespace Renci.SshNet.Tests.Classes.Channels
 
                 localPortListener.Connected += socket =>
                 {
-                    var channel = new ChannelDirectTcpip(_sessionMock.Object, _localChannelNumber, _localWindowSize,
-                        _localPacketSize);
+                    var channel = new ChannelDirectTcpip(_sessionMock.Object,
+                                                         _localChannelNumber,
+                                                         _localWindowSize,
+                                                         _localPacketSize);
                     channel.Open(_remoteHost, _port, _forwardedPortMock.Object, socket);
 
                     var signalSessionErrorOccurredThread =
                         new Thread(() =>
-                            {
-                                // sleep for a short period to allow channel to actually start receiving from socket
-                                Thread.Sleep(100);
-                                // raise ErrorOccured event on session
-                                _sessionMock.Raise(s => s.ErrorOccured += null,
-                                    new ExceptionEventArgs(new SystemException()));
-                            });
+                        {
+                            // sleep for a short period to allow channel to actually start receiving from socket
+                            Thread.Sleep(100);
+                            // raise ErrorOccured event on session
+                            _sessionMock.Raise(s => s.ErrorOccured += null,
+                                               new ExceptionEventArgs(new SystemException()));
+                        });
                     signalSessionErrorOccurredThread.Start();
 
                     channel.Bind();
@@ -152,34 +164,49 @@ namespace Renci.SshNet.Tests.Classes.Channels
         [TestMethod]
         public void SocketShouldBeClosedAndEofShouldBeSentToServerWhenClientShutsDownSocket()
         {
-            _sessionMock.Setup(p => p.IsConnected).Returns(true);
-            _sessionMock.Setup(p => p.SendMessage(It.IsAny<ChannelOpenMessage>()))
-                .Callback<Message>(m => _sessionMock.Raise(p => p.ChannelOpenConfirmationReceived += null,
-                    new MessageEventArgs<ChannelOpenConfirmationMessage>(
-                        new ChannelOpenConfirmationMessage(((ChannelOpenMessage) m).LocalChannelNumber,
-                            _remoteWindowSize, _remotePacketSize, _remoteChannelNumber))));
-            _sessionMock.Setup(p => p.WaitOnHandle(It.IsAny<EventWaitHandle>()))
-                .Callback<WaitHandle>(p => p.WaitOne(Session.Infinite));
-            _sessionMock.Setup(p => p.ConnectionInfo).Returns(_connectionInfoMock.Object);
-            _connectionInfoMock.Setup(p => p.Timeout).Returns(TimeSpan.FromSeconds(60));
-            _sessionMock.Setup(p => p.TrySendMessage(It.IsAny<ChannelEofMessage>()))
-                .Returns(true)
-                .Callback<Message>(
-                    m => new Thread(() =>
-                        {
-                            Thread.Sleep(50);
-                            _sessionMock.Raise(s => s.ChannelEofReceived += null,
-                                new MessageEventArgs<ChannelEofMessage>(new ChannelEofMessage(_localChannelNumber)));
-                        }).Start());
-            _sessionMock.Setup(p => p.TrySendMessage(It.IsAny<ChannelCloseMessage>()))
-                .Returns(true)
-                .Callback<Message>(
-                    m => new Thread(() =>
-                        {
-                            Thread.Sleep(50);
-                            _sessionMock.Raise(s => s.ChannelCloseReceived += null,
-                                new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
-                        }).Start());
+            var sequence = new MockSequence();
+
+            _sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
+            _sessionMock.InSequence(sequence)
+                        .Setup(p => p.SendMessage(It.IsAny<ChannelOpenMessage>()))
+                        .Callback<Message>(m => _sessionMock.Raise(p => p.ChannelOpenConfirmationReceived += null,
+                                                                   new MessageEventArgs<ChannelOpenConfirmationMessage>(
+                                                                       new ChannelOpenConfirmationMessage(((ChannelOpenMessage) m).LocalChannelNumber,
+                                                                                                          _remoteWindowSize,
+                                                                                                          _remotePacketSize,
+                                                                                                          _remoteChannelNumber))));
+            _sessionMock.InSequence(sequence)
+                        .Setup(p => p.WaitOnHandle(It.IsAny<EventWaitHandle>()))
+                        .Callback<WaitHandle>(p => p.WaitOne(Session.Infinite));
+            _sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
+            _sessionMock.InSequence(sequence)
+                        .Setup(p => p.TrySendMessage(It.IsAny<ChannelEofMessage>()))
+                        .Returns(true)
+                        .Callback<Message>(
+                            m => new Thread(() =>
+                            {
+                                Thread.Sleep(50);
+                                _sessionMock.Raise(s => s.ChannelEofReceived += null,
+                                                   new MessageEventArgs<ChannelEofMessage>(new ChannelEofMessage(_localChannelNumber)));
+                            }).Start());
+            _sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
+            _sessionMock.InSequence(sequence)
+                        .Setup(p => p.TrySendMessage(It.IsAny<ChannelCloseMessage>()))
+                        .Returns(true)
+                        .Callback<Message>(
+                            m => new Thread(() =>
+                            {
+                                Thread.Sleep(50);
+                                _sessionMock.Raise(s => s.ChannelCloseReceived += null,
+                                                   new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
+                            }).Start());
+            _sessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(_connectionInfoMock.Object);
+            _connectionInfoMock.InSequence(sequence).Setup(p => p.ChannelCloseTimeout).Returns(_channelCloseTimeout);
+            _sessionMock.InSequence(sequence)
+                        .Setup(p => p.TryWait(It.IsAny<EventWaitHandle>(), _channelCloseTimeout))
+                        .Callback<WaitHandle, TimeSpan>((waitHandle, channelCloseTimeout) => waitHandle.WaitOne())
+                        .Returns(WaitResult.Success);
+
             var channelBindFinishedWaitHandle = new ManualResetEvent(false);
             Socket handler = null;
             ChannelDirectTcpip channel = null;
@@ -190,17 +217,19 @@ namespace Renci.SshNet.Tests.Classes.Channels
                 localPortListener.Start();
 
                 localPortListener.Connected += socket =>
-                    {
-                        channel = new ChannelDirectTcpip(_sessionMock.Object, _localChannelNumber, _localWindowSize,
-                            _localPacketSize);
-                        channel.Open(_remoteHost, _port, _forwardedPortMock.Object, socket);
-                        channel.Bind();
-                        channel.Dispose();
+                {
+                    channel = new ChannelDirectTcpip(_sessionMock.Object,
+                                                     _localChannelNumber,
+                                                     _localWindowSize,
+                                                     _localPacketSize);
+                    channel.Open(_remoteHost, _port, _forwardedPortMock.Object, socket);
+                    channel.Bind();
+                    channel.Dispose();
 
-                        handler = socket;
+                    handler = socket;
 
-                        channelBindFinishedWaitHandle.Set();
-                    };
+                    channelBindFinishedWaitHandle.Set();
+                };
 
                 var client = new Socket(localPortEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                 client.Connect(localPortEndPoint);

+ 21 - 16
src/Renci.SshNet.Tests/Classes/Channels/ChannelDirectTcpipTest_Dispose_SessionIsConnectedAndChannelIsOpen.cs

@@ -18,6 +18,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
     public class ChannelDirectTcpipTest_Dispose_SessionIsConnectedAndChannelIsOpen
     {
         private Mock<ISession> _sessionMock;
+        private Mock<IConnectionInfo> _connectionInfoMock;
         private Mock<IForwardedPort> _forwardedPortMock;
         private ChannelDirectTcpip _channel;
         private uint _localChannelNumber;
@@ -26,6 +27,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private uint _remoteWindowSize;
         private uint _remotePacketSize;
         private uint _remoteChannelNumber;
+        private TimeSpan _channelCloseTimeout;
         private string _remoteHost;
         private uint _port;
         private AsyncSocketListener _listener;
@@ -60,9 +62,11 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private void Arrange()
         {
             var random = new Random();
+
             _localChannelNumber = (uint) random.Next(0, int.MaxValue);
             _localWindowSize = (uint) random.Next(2000, 3000);
             _localPacketSize = (uint) random.Next(1000, 2000);
+            _channelCloseTimeout = TimeSpan.FromSeconds(random.Next(10, 20));
             _remoteHost = random.Next().ToString(CultureInfo.InvariantCulture);
             _port = (uint) random.Next(IPEndPoint.MinPort, IPEndPoint.MaxPort);
             _channelBindFinishedWaitHandle = new ManualResetEvent(false);
@@ -74,6 +78,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
             _remotePacketSize = (uint)random.Next(100, 200);
 
             _sessionMock = new Mock<ISession>(MockBehavior.Strict);
+            _connectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
             _forwardedPortMock = new Mock<IForwardedPort>(MockBehavior.Strict);
 
             var sequence = new MockSequence();
@@ -102,19 +107,20 @@ namespace Renci.SshNet.Tests.Classes.Channels
                 .Returns(true);
             _sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
             _sessionMock.InSequence(sequence)
-                .Setup(
-                    p => p.TrySendMessage(It.Is<ChannelCloseMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)))
+                .Setup(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)))
                 .Returns(true);
+            _sessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(_connectionInfoMock.Object);
+            _connectionInfoMock.InSequence(sequence).Setup(p => p.ChannelCloseTimeout).Returns(_channelCloseTimeout);
             _sessionMock.InSequence(sequence)
-                .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
-                .Callback<WaitHandle>(
-                    w =>
-                    {
-                        _sessionMock.Raise(
-                            s => s.ChannelCloseReceived += null,
-                            new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
-                        w.WaitOne();
-                    });
+                        .Setup(p => p.TryWait(It.IsAny<EventWaitHandle>(), _channelCloseTimeout))
+                        .Callback<WaitHandle, TimeSpan>((waitHandle, channelCloseTimeout) =>
+                        {
+                            _sessionMock.Raise(
+                                s => s.ChannelCloseReceived += null,
+                                new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
+                            waitHandle.WaitOne();
+                        })
+                        .Returns(WaitResult.Success);
 
             var localEndpoint = new IPEndPoint(IPAddress.Loopback, 8122);
             _listener = new AsyncSocketListener(localEndpoint);
@@ -122,11 +128,10 @@ namespace Renci.SshNet.Tests.Classes.Channels
                 {
                     try
                     {
-                        _channel = new ChannelDirectTcpip(
-                            _sessionMock.Object,
-                            _localChannelNumber,
-                            _localWindowSize,
-                            _localPacketSize);
+                        _channel = new ChannelDirectTcpip(_sessionMock.Object,
+                                                          _localChannelNumber,
+                                                          _localWindowSize,
+                                                          _localPacketSize);
                         _channel.Open(_remoteHost, _port, _forwardedPortMock.Object, socket);
                         _channel.Bind();
                     }

+ 9 - 5
src/Renci.SshNet.Tests/Classes/Channels/ChannelForwardedTcpipTest_Dispose_SessionIsConnectedAndChannelIsOpen.cs

@@ -25,6 +25,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private uint _remoteWindowSize;
         private uint _remotePacketSize;
         private uint _remoteChannelNumber;
+        private TimeSpan _channelCloseTimeout;
         private IPEndPoint _remoteEndpoint;
         private AsyncSocketListener _remoteListener;
         private EventWaitHandle _channelBindFinishedWaitHandle;
@@ -72,6 +73,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
             _remoteChannelNumber = (uint) random.Next(0, int.MaxValue);
             _remoteWindowSize = (uint) random.Next(0, int.MaxValue);
             _remotePacketSize = (uint) random.Next(100, 200);
+            _channelCloseTimeout = TimeSpan.FromSeconds(random.Next(10, 20));
             _channelBindFinishedWaitHandle = new ManualResetEvent(false);
             _channelException = null;
             _connectedRegister = new List<Socket>();
@@ -109,16 +111,18 @@ namespace Renci.SshNet.Tests.Classes.Channels
                 .Setup(
                     p => p.TrySendMessage(It.Is<ChannelCloseMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)))
                 .Returns(true);
+            _sessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(_connectionInfoMock.Object);
+            _connectionInfoMock.InSequence(sequence).Setup(p => p.ChannelCloseTimeout).Returns(_channelCloseTimeout);
             _sessionMock.InSequence(sequence)
-                .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
-                .Callback<WaitHandle>(
-                    w =>
+                        .Setup(p => p.TryWait(It.IsAny<EventWaitHandle>(), _channelCloseTimeout))
+                        .Callback<WaitHandle, TimeSpan>((waitHandle, channelCloseTimeout) =>
                         {
                             _sessionMock.Raise(
                                 s => s.ChannelCloseReceived += null,
                                 new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
-                            w.WaitOne();
-                        });
+                            waitHandle.WaitOne();
+                        })
+                        .Returns(WaitResult.Success);
 
             _remoteListener = new AsyncSocketListener(_remoteEndpoint);
             _remoteListener.Connected += socket => _connectedRegister.Add(socket);

+ 37 - 0
src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTestBase.cs

@@ -0,0 +1,37 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+
+namespace Renci.SshNet.Tests.Classes.Channels
+{
+    public abstract class ChannelSessionTestBase
+    {
+        internal Mock<ISession> SessionMock { get; private set; }
+        internal Mock<IConnectionInfo> ConnectionInfoMock { get; private set; }
+
+        [TestInitialize]
+        public void Initialize()
+        {
+            Arrange();
+            Act();
+        }
+
+        protected abstract void SetupData();
+
+        protected void CreateMocks()
+        {
+            SessionMock = new Mock<ISession>(MockBehavior.Strict);
+            ConnectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
+        }
+
+        protected abstract void SetupMocks();
+
+        protected virtual void Arrange()
+        {
+            SetupData();
+            CreateMocks();
+            SetupMocks();
+        }
+
+        protected abstract void Act();
+    }
+}

+ 41 - 38
src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Dispose_Disposed.cs

@@ -10,10 +10,8 @@ using Renci.SshNet.Messages.Connection;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelSessionTest_Dispose_Disposed
+    public class ChannelSessionTest_Dispose_Disposed : ChannelSessionTestBase
     {
-        private Mock<ISession> _sessionMock;
-        private Mock<IConnectionInfo> _connectionInfoMock;
         private ChannelSession _channel;
         private uint _localChannelNumber;
         private uint _localWindowSize;
@@ -21,38 +19,35 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private uint _remoteWindowSize;
         private uint _remotePacketSize;
         private uint _remoteChannelNumber;
+        private TimeSpan _channelCloseTimeout;
         private SemaphoreLight _sessionSemaphore;
         private IList<ChannelEventArgs> _channelClosedRegister;
         private List<ExceptionEventArgs> _channelExceptionRegister;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
+
             _localChannelNumber = (uint)random.Next(0, int.MaxValue);
             _localWindowSize = (uint)random.Next(2000, 3000);
             _localPacketSize = (uint)random.Next(1000, 2000);
             _remoteChannelNumber = (uint)random.Next(0, int.MaxValue);
             _remoteWindowSize = (uint)random.Next(0, int.MaxValue);
             _remotePacketSize = (uint)random.Next(100, 200);
+            _channelCloseTimeout = TimeSpan.FromSeconds(random.Next(10, 20));
             _sessionSemaphore = new SemaphoreLight(1);
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
-            _connectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
-
+        protected override void SetupMocks()
+        {
             var sequence = new MockSequence();
-            _sessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(_connectionInfoMock.Object);
-            _connectionInfoMock.InSequence(sequence).Setup(p => p.RetryAttempts).Returns(1);
-            _sessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
-            _sessionMock.InSequence(sequence)
+
+            SessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(sequence).Setup(p => p.RetryAttempts).Returns(1);
+            SessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
+            SessionMock.InSequence(sequence)
                 .Setup(
                     p =>
                         p.SendMessage(
@@ -61,12 +56,12 @@ namespace Renci.SshNet.Tests.Classes.Channels
                                     m.LocalChannelNumber == _localChannelNumber &&
                                     m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
                                     m.Info is SessionChannelOpenInfo)));
-            _sessionMock.InSequence(sequence)
+            SessionMock.InSequence(sequence)
                 .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
                 .Callback<WaitHandle>(
                     w =>
                         {
-                            _sessionMock.Raise(
+                            SessionMock.Raise(
                                 s => s.ChannelOpenConfirmationReceived += null,
                                 new MessageEventArgs<ChannelOpenConfirmationMessage>(
                                     new ChannelOpenConfirmationMessage(
@@ -76,31 +71,39 @@ namespace Renci.SshNet.Tests.Classes.Channels
                                         _remoteChannelNumber)));
                         w.WaitOne();
                     });
-            _sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
-            _sessionMock.InSequence(sequence)
+            SessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
+            SessionMock.InSequence(sequence)
                 .Setup(p => p.TrySendMessage(It.Is<ChannelEofMessage>(m => m.LocalChannelNumber == _remoteChannelNumber))).Returns(true);
-            _sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
-            _sessionMock.InSequence(sequence)
+            SessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
+            SessionMock.InSequence(sequence)
                 .Setup(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(m => m.LocalChannelNumber == _remoteChannelNumber))).Returns(true);
-            _sessionMock.InSequence(sequence)
-                .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
-                .Callback<WaitHandle>(
-                    w =>
-                    {
-                        _sessionMock.Raise(
-                            s => s.ChannelCloseReceived += null,
-                            new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
-                        w.WaitOne();
-                    });
+            SessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(sequence).Setup(p => p.ChannelCloseTimeout).Returns(_channelCloseTimeout);
+            SessionMock.InSequence(sequence)
+                       .Setup(p => p.TryWait(It.IsNotNull<WaitHandle>(), _channelCloseTimeout))
+                       .Callback<WaitHandle, TimeSpan>(
+                           (waitHandle, channelCloseTimeout) =>
+                           {
+                               SessionMock.Raise(
+                                   s => s.ChannelCloseReceived += null,
+                                   new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
+                               waitHandle.WaitOne();
+                           })
+                       .Returns(WaitResult.Success);
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
 
-            _channel = new ChannelSession(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelSession(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Closed += (sender, args) => _channelClosedRegister.Add(args);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.Open();
             _channel.Dispose();
         }
 
-        protected virtual void Act()
+        protected override void Act()
         {
             _channel.Dispose();
         }
@@ -113,13 +116,13 @@ namespace Renci.SshNet.Tests.Classes.Channels
         [TestMethod]
         public void ChannelEofMessageShouldBeSentOnce()
         {
-            _sessionMock.Verify(p => p.TrySendMessage(It.Is<ChannelEofMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)), Times.Once);
+            SessionMock.Verify(p => p.TrySendMessage(It.Is<ChannelEofMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)), Times.Once);
         }
 
         [TestMethod]
         public void ChannelCloseMessageShouldBeSentOnce()
         {
-            _sessionMock.Verify(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)), Times.Once);
+            SessionMock.Verify(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)), Times.Once);
         }
 
         [TestMethod]

+ 39 - 36
src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_ChannelCloseAndChannelEofReceived_DisposeInEventHandler.cs

@@ -11,52 +11,47 @@ using Renci.SshNet.Tests.Common;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_ChannelCloseAndChannelEofReceived_DisposeInEventHandler
+    public class ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_ChannelCloseAndChannelEofReceived_DisposeInEventHandler : ChannelSessionTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localChannelNumber;
         private uint _localWindowSize;
         private uint _localPacketSize;
         private uint _remoteChannelNumber;
         private uint _remoteWindowSize;
         private uint _remotePacketSize;
+        private TimeSpan _channelCloseTimeout;
         private IList<ChannelEventArgs> _channelClosedRegister;
         private List<ExceptionEventArgs> _channelExceptionRegister;
         private ChannelSession _channel;
-        private Mock<IConnectionInfo> _connectionInfoMock;
         private MockSequence _sequence;
         private SemaphoreLight _sessionSemaphore;
         private int _initialSessionSemaphoreCount;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _localWindowSize = (uint)random.Next(0, int.MaxValue);
-            _localPacketSize = (uint)random.Next(0, int.MaxValue);
-            _remoteChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _remoteWindowSize = (uint)random.Next(0, int.MaxValue);
-            _remotePacketSize = (uint)random.Next(0, int.MaxValue);
+
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _localWindowSize = (uint) random.Next(0, int.MaxValue);
+            _localPacketSize = (uint) random.Next(0, int.MaxValue);
+            _remoteChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _remoteWindowSize = (uint) random.Next(0, int.MaxValue);
+            _remotePacketSize = (uint) random.Next(0, int.MaxValue);
+            _channelCloseTimeout = TimeSpan.FromSeconds(random.Next(10, 20));
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
             _initialSessionSemaphoreCount = random.Next(10, 20);
             _sessionSemaphore = new SemaphoreLight(_initialSessionSemaphoreCount);
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
-            _connectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
-
+        protected override void SetupMocks()
+        {
             _sequence = new MockSequence();
-            _sessionMock.InSequence(_sequence).Setup(p => p.ConnectionInfo).Returns(_connectionInfoMock.Object);
-            _connectionInfoMock.InSequence(_sequence).Setup(p => p.RetryAttempts).Returns(1);
-            _sessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
-            _sessionMock.InSequence(_sequence)
+
+            SessionMock.InSequence(_sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(_sequence).Setup(p => p.RetryAttempts).Returns(1);
+            SessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
+            SessionMock.InSequence(_sequence)
                         .Setup(
                             p =>
                                 p.SendMessage(
@@ -65,12 +60,12 @@ namespace Renci.SshNet.Tests.Classes.Channels
                                             m.LocalChannelNumber == _localChannelNumber &&
                                             m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
                                             m.Info is SessionChannelOpenInfo)));
-            _sessionMock.InSequence(_sequence)
+            SessionMock.InSequence(_sequence)
                         .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
                         .Callback<WaitHandle>(
                             w =>
                             {
-                                _sessionMock.Raise(
+                                SessionMock.Raise(
                                     s => s.ChannelOpenConfirmationReceived += null,
                                     new MessageEventArgs<ChannelOpenConfirmationMessage>(
                                         new ChannelOpenConfirmationMessage(
@@ -80,15 +75,23 @@ namespace Renci.SshNet.Tests.Classes.Channels
                                             _remoteChannelNumber)));
                                 w.WaitOne();
                             });
-            _sessionMock.InSequence(_sequence).Setup(p => p.IsConnected).Returns(true);
-            _sessionMock.InSequence(_sequence)
+            SessionMock.InSequence(_sequence).Setup(p => p.IsConnected).Returns(true);
+            SessionMock.InSequence(_sequence)
                         .Setup(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)))
                         .Returns(true);
-            _sessionMock.InSequence(_sequence)
-                        .Setup(s => s.WaitOnHandle(It.IsNotNull<EventWaitHandle>()))
-                        .Callback<WaitHandle>(w => w.WaitOne());
+            SessionMock.InSequence(_sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(_sequence).Setup(p => p.ChannelCloseTimeout).Returns(_channelCloseTimeout);
+            SessionMock.InSequence(_sequence)
+                       .Setup(p => p.TryWait(It.IsNotNull<WaitHandle>(), _channelCloseTimeout))
+                       .Callback<WaitHandle, TimeSpan>((waitHandle, channelCloseTimeout) => waitHandle.WaitOne())
+                       .Returns(WaitResult.Success);
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
 
-            _channel = new ChannelSession(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelSession(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Closed += (sender, args) =>
                 {
                     _channelClosedRegister.Add(args);
@@ -97,13 +100,13 @@ namespace Renci.SshNet.Tests.Classes.Channels
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.Open();
 
-            _sessionMock.Raise(p => p.ChannelEofReceived += null,
+            SessionMock.Raise(p => p.ChannelEofReceived += null,
                                new MessageEventArgs<ChannelEofMessage>(new ChannelEofMessage(_localChannelNumber)));
-            _sessionMock.Raise(p => p.ChannelCloseReceived += null,
+            SessionMock.Raise(p => p.ChannelCloseReceived += null,
                                new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
         }
 
-        private void Act()
+        protected override void Act()
         {
             _channel.Dispose();
         }
@@ -133,4 +136,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
             Assert.IsFalse(_channel.IsOpen);
         }
     }
-}
+}

+ 55 - 57
src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_ChannelCloseAndChannelEofReceived_SendChannelCloseMessageFailure.cs

@@ -10,9 +10,8 @@ using Renci.SshNet.Messages.Connection;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_ChannelCloseAndChannelEofReceived_SendChannelCloseMessageFailure
+    public class ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_ChannelCloseAndChannelEofReceived_SendChannelCloseMessageFailure : ChannelSessionTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localChannelNumber;
         private uint _localWindowSize;
         private uint _localPacketSize;
@@ -22,83 +21,82 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private IList<ChannelEventArgs> _channelClosedRegister;
         private List<ExceptionEventArgs> _channelExceptionRegister;
         private ChannelSession _channel;
-        private Mock<IConnectionInfo> _connectionInfoMock;
         private MockSequence _sequence;
         private SemaphoreLight _sessionSemaphore;
         private int _initialSessionSemaphoreCount;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _localWindowSize = (uint)random.Next(0, int.MaxValue);
-            _localPacketSize = (uint)random.Next(0, int.MaxValue);
-            _remoteChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _remoteWindowSize = (uint)random.Next(0, int.MaxValue);
-            _remotePacketSize = (uint)random.Next(0, int.MaxValue);
+
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _localWindowSize = (uint) random.Next(0, int.MaxValue);
+            _localPacketSize = (uint) random.Next(0, int.MaxValue);
+            _remoteChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _remoteWindowSize = (uint) random.Next(0, int.MaxValue);
+            _remotePacketSize = (uint) random.Next(0, int.MaxValue);
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
             _initialSessionSemaphoreCount = random.Next(10, 20);
             _sessionSemaphore = new SemaphoreLight(_initialSessionSemaphoreCount);
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
-            _connectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
-
+        protected override void SetupMocks()
+        {
             _sequence = new MockSequence();
-            _sessionMock.InSequence(_sequence).Setup(p => p.ConnectionInfo).Returns(_connectionInfoMock.Object);
-            _connectionInfoMock.InSequence(_sequence).Setup(p => p.RetryAttempts).Returns(1);
-            _sessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
-            _sessionMock.InSequence(_sequence)
-                .Setup(
-                    p =>
-                        p.SendMessage(
-                            It.Is<ChannelOpenMessage>(
-                                m =>
-                                    m.LocalChannelNumber == _localChannelNumber &&
-                                    m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
-                                    m.Info is SessionChannelOpenInfo)));
-            _sessionMock.InSequence(_sequence)
-                .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
-                .Callback<WaitHandle>(
-                    w =>
-                    {
-                        _sessionMock.Raise(
-                            s => s.ChannelOpenConfirmationReceived += null,
-                            new MessageEventArgs<ChannelOpenConfirmationMessage>(
-                                new ChannelOpenConfirmationMessage(
-                                    _localChannelNumber,
-                                    _remoteWindowSize,
-                                    _remotePacketSize,
-                                    _remoteChannelNumber)));
-                        w.WaitOne();
-                    });
-            _sessionMock.Setup(p => p.IsConnected).Returns(true);
-            _sessionMock.InSequence(_sequence)
-                .Setup(
-                    p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)))
-                .Returns(false);
 
-            _channel = new ChannelSession(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            SessionMock.InSequence(_sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(_sequence).Setup(p => p.RetryAttempts).Returns(1);
+            SessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
+            SessionMock.InSequence(_sequence)
+                        .Setup(
+                            p =>
+                                p.SendMessage(
+                                    It.Is<ChannelOpenMessage>(
+                                        m =>
+                                            m.LocalChannelNumber == _localChannelNumber &&
+                                            m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
+                                            m.Info is SessionChannelOpenInfo)));
+            SessionMock.InSequence(_sequence)
+                        .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
+                        .Callback<WaitHandle>(
+                            w =>
+                            {
+                                SessionMock.Raise(
+                                    s => s.ChannelOpenConfirmationReceived += null,
+                                    new MessageEventArgs<ChannelOpenConfirmationMessage>(
+                                        new ChannelOpenConfirmationMessage(
+                                            _localChannelNumber,
+                                            _remoteWindowSize,
+                                            _remotePacketSize,
+                                            _remoteChannelNumber)));
+                                w.WaitOne();
+                            });
+            SessionMock.Setup(p => p.IsConnected).Returns(true);
+            SessionMock.InSequence(_sequence)
+                        .Setup(
+                            p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)))
+                        .Returns(false);
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
+
+            _channel = new ChannelSession(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Closed += (sender, args) => _channelClosedRegister.Add(args);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.Open();
 
-            _sessionMock.Raise(
+            SessionMock.Raise(
                 p => p.ChannelEofReceived += null,
                 new MessageEventArgs<ChannelEofMessage>(new ChannelEofMessage(_localChannelNumber)));
-            _sessionMock.Raise(
+            SessionMock.Raise(
                 p => p.ChannelCloseReceived += null,
                 new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
         }
 
-        private void Act()
+        protected override void Act()
         {
             _channel.Dispose();
         }
@@ -128,4 +126,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
             Assert.IsFalse(_channel.IsOpen);
         }
     }
-}
+}

+ 57 - 55
src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_ChannelCloseAndChannelEofReceived_SendChannelCloseMessageSuccess.cs

@@ -11,98 +11,100 @@ using Renci.SshNet.Tests.Common;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_ChannelCloseAndChannelEofReceived_SendChannelCloseMessageSuccess
+    public class ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_ChannelCloseAndChannelEofReceived_SendChannelCloseMessageSuccess : ChannelSessionTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localChannelNumber;
         private uint _localWindowSize;
         private uint _localPacketSize;
         private uint _remoteChannelNumber;
         private uint _remoteWindowSize;
         private uint _remotePacketSize;
+        private TimeSpan _channelCloseTimeout;
         private IList<ChannelEventArgs> _channelClosedRegister;
         private List<ExceptionEventArgs> _channelExceptionRegister;
         private ChannelSession _channel;
-        private Mock<IConnectionInfo> _connectionInfoMock;
-        private MockSequence _sequence;
         private SemaphoreLight _sessionSemaphore;
         private int _initialSessionSemaphoreCount;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
+
             _localChannelNumber = (uint) random.Next(0, int.MaxValue);
             _localWindowSize = (uint) random.Next(0, int.MaxValue);
             _localPacketSize = (uint) random.Next(0, int.MaxValue);
             _remoteChannelNumber = (uint) random.Next(0, int.MaxValue);
             _remoteWindowSize = (uint) random.Next(0, int.MaxValue);
             _remotePacketSize = (uint) random.Next(0, int.MaxValue);
+            _channelCloseTimeout = TimeSpan.FromSeconds(random.Next(10, 20));
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
             _initialSessionSemaphoreCount = random.Next(10, 20);
             _sessionSemaphore = new SemaphoreLight(_initialSessionSemaphoreCount);
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
-            _connectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
+        protected override void SetupMocks()
+        {
+            var sequence = new MockSequence();
+
+            SessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(sequence).Setup(p => p.RetryAttempts).Returns(1);
+            SessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
+            SessionMock.InSequence(sequence)
+                        .Setup(
+                            p =>
+                                p.SendMessage(
+                                    It.Is<ChannelOpenMessage>(
+                                        m =>
+                                            m.LocalChannelNumber == _localChannelNumber &&
+                                            m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
+                                            m.Info is SessionChannelOpenInfo)));
+            SessionMock.InSequence(sequence)
+                        .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
+                        .Callback<WaitHandle>(
+                            w =>
+                            {
+                                SessionMock.Raise(
+                                    s => s.ChannelOpenConfirmationReceived += null,
+                                    new MessageEventArgs<ChannelOpenConfirmationMessage>(
+                                        new ChannelOpenConfirmationMessage(
+                                            _localChannelNumber,
+                                            _remoteWindowSize,
+                                            _remotePacketSize,
+                                            _remoteChannelNumber)));
+                                w.WaitOne();
+                            });
+            SessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
+            SessionMock.InSequence(sequence)
+                        .Setup(
+                            p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)))
+                        .Returns(true);
+            SessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(sequence).Setup(p => p.ChannelCloseTimeout).Returns(_channelCloseTimeout);
+            SessionMock.InSequence(sequence)
+                       .Setup(p => p.TryWait(It.IsNotNull<WaitHandle>(), _channelCloseTimeout))
+                       .Callback<WaitHandle, TimeSpan>((waitHandle, channelCloseTimeout) => waitHandle.WaitOne())
+                       .Returns(WaitResult.Success);
+        }
 
-            _sequence = new MockSequence();
-            _sessionMock.InSequence(_sequence).Setup(p => p.ConnectionInfo).Returns(_connectionInfoMock.Object);
-            _connectionInfoMock.InSequence(_sequence).Setup(p => p.RetryAttempts).Returns(1);
-            _sessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
-            _sessionMock.InSequence(_sequence)
-                .Setup(
-                    p =>
-                        p.SendMessage(
-                            It.Is<ChannelOpenMessage>(
-                                m =>
-                                    m.LocalChannelNumber == _localChannelNumber &&
-                                    m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
-                                    m.Info is SessionChannelOpenInfo)));
-            _sessionMock.InSequence(_sequence)
-                .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
-                .Callback<WaitHandle>(
-                    w =>
-                    {
-                        _sessionMock.Raise(
-                            s => s.ChannelOpenConfirmationReceived += null,
-                            new MessageEventArgs<ChannelOpenConfirmationMessage>(
-                                new ChannelOpenConfirmationMessage(
-                                    _localChannelNumber,
-                                    _remoteWindowSize,
-                                    _remotePacketSize,
-                                    _remoteChannelNumber)));
-                        w.WaitOne();
-                    });
-            _sessionMock.InSequence(_sequence).Setup(p => p.IsConnected).Returns(true);
-            _sessionMock.InSequence(_sequence)
-                .Setup(
-                    p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)))
-                .Returns(true);
-            _sessionMock.InSequence(_sequence)
-                .Setup(s => s.WaitOnHandle(It.IsNotNull<EventWaitHandle>()))
-                .Callback<WaitHandle>(w => w.WaitOne());
+        protected override void Arrange()
+        {
+            base.Arrange();
 
-            _channel = new ChannelSession(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelSession(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Closed += (sender, args) => _channelClosedRegister.Add(args);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.Open();
 
-            _sessionMock.Raise(
+            SessionMock.Raise(
                 p => p.ChannelEofReceived += null,
                 new MessageEventArgs<ChannelEofMessage>(new ChannelEofMessage(_localChannelNumber)));
-            _sessionMock.Raise(
+            SessionMock.Raise(
                 p => p.ChannelCloseReceived += null,
                 new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
         }
 
-        private void Act()
+        protected override void Act()
         {
             _channel.Dispose();
         }
@@ -132,4 +134,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
             Assert.IsFalse(_channel.IsOpen);
         }
     }
-}
+}

+ 54 - 56
src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_ChannelCloseReceived_SendChannelCloseMessageFailure.cs

@@ -10,9 +10,8 @@ using Renci.SshNet.Messages.Connection;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_ChannelCloseReceived_SendChannelCloseMessageFailure
+    public class ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_ChannelCloseReceived_SendChannelCloseMessageFailure : ChannelSessionTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localChannelNumber;
         private uint _localWindowSize;
         private uint _localPacketSize;
@@ -22,80 +21,79 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private IList<ChannelEventArgs> _channelClosedRegister;
         private List<ExceptionEventArgs> _channelExceptionRegister;
         private ChannelSession _channel;
-        private Mock<IConnectionInfo> _connectionInfoMock;
         private MockSequence _sequence;
         private SemaphoreLight _sessionSemaphore;
         private int _initialSessionSemaphoreCount;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _localWindowSize = (uint)random.Next(0, int.MaxValue);
-            _localPacketSize = (uint)random.Next(0, int.MaxValue);
-            _remoteChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _remoteWindowSize = (uint)random.Next(0, int.MaxValue);
-            _remotePacketSize = (uint)random.Next(0, int.MaxValue);
+
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _localWindowSize = (uint) random.Next(0, int.MaxValue);
+            _localPacketSize = (uint) random.Next(0, int.MaxValue);
+            _remoteChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _remoteWindowSize = (uint) random.Next(0, int.MaxValue);
+            _remotePacketSize = (uint) random.Next(0, int.MaxValue);
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
             _initialSessionSemaphoreCount = random.Next(10, 20);
             _sessionSemaphore = new SemaphoreLight(_initialSessionSemaphoreCount);
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
-            _connectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
-
+        protected override void SetupMocks()
+        {
             _sequence = new MockSequence();
-            _sessionMock.InSequence(_sequence).Setup(p => p.ConnectionInfo).Returns(_connectionInfoMock.Object);
-            _connectionInfoMock.InSequence(_sequence).Setup(p => p.RetryAttempts).Returns(1);
-            _sessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
-            _sessionMock.InSequence(_sequence)
-                .Setup(
-                    p =>
-                        p.SendMessage(
-                            It.Is<ChannelOpenMessage>(
-                                m =>
-                                    m.LocalChannelNumber == _localChannelNumber &&
-                                    m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
-                                    m.Info is SessionChannelOpenInfo)));
-            _sessionMock.InSequence(_sequence)
-                .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
-                .Callback<WaitHandle>(
-                    w =>
-                    {
-                        _sessionMock.Raise(
-                            s => s.ChannelOpenConfirmationReceived += null,
-                            new MessageEventArgs<ChannelOpenConfirmationMessage>(
-                                new ChannelOpenConfirmationMessage(
-                                    _localChannelNumber,
-                                    _remoteWindowSize,
-                                    _remotePacketSize,
-                                    _remoteChannelNumber)));
-                        w.WaitOne();
-                    });
-            _sessionMock.Setup(p => p.IsConnected).Returns(true);
-            _sessionMock.InSequence(_sequence)
-                .Setup(
-                    p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)))
-                .Returns(false);
 
-            _channel = new ChannelSession(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            SessionMock.InSequence(_sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(_sequence).Setup(p => p.RetryAttempts).Returns(1);
+            SessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
+            SessionMock.InSequence(_sequence)
+                        .Setup(
+                            p =>
+                                p.SendMessage(
+                                    It.Is<ChannelOpenMessage>(
+                                        m =>
+                                            m.LocalChannelNumber == _localChannelNumber &&
+                                            m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
+                                            m.Info is SessionChannelOpenInfo)));
+            SessionMock.InSequence(_sequence)
+                        .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
+                        .Callback<WaitHandle>(
+                            w =>
+                            {
+                                SessionMock.Raise(
+                                    s => s.ChannelOpenConfirmationReceived += null,
+                                    new MessageEventArgs<ChannelOpenConfirmationMessage>(
+                                        new ChannelOpenConfirmationMessage(
+                                            _localChannelNumber,
+                                            _remoteWindowSize,
+                                            _remotePacketSize,
+                                            _remoteChannelNumber)));
+                                w.WaitOne();
+                            });
+            SessionMock.Setup(p => p.IsConnected).Returns(true);
+            SessionMock.InSequence(_sequence)
+                        .Setup(
+                            p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)))
+                        .Returns(false);
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
+
+            _channel = new ChannelSession(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Closed += (sender, args) => _channelClosedRegister.Add(args);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.Open();
 
-            _sessionMock.Raise(
+            SessionMock.Raise(
                 p => p.ChannelCloseReceived += null,
                 new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
         }
 
-        private void Act()
+        protected override void Act()
         {
             _channel.Dispose();
         }
@@ -125,4 +123,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
             Assert.IsFalse(_channel.IsOpen);
         }
     }
-}
+}

+ 31 - 29
src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_ChannelCloseReceived_SendChannelCloseMessageSuccess.cs

@@ -11,52 +11,46 @@ using Renci.SshNet.Tests.Common;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_ChannelCloseReceived_SendChannelCloseMessageSuccess
+    public class ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_ChannelCloseReceived_SendChannelCloseMessageSuccess : ChannelSessionTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localChannelNumber;
         private uint _localWindowSize;
         private uint _localPacketSize;
         private uint _remoteChannelNumber;
         private uint _remoteWindowSize;
         private uint _remotePacketSize;
+        private TimeSpan _channelCloseTimeout;
         private IList<ChannelEventArgs> _channelClosedRegister;
         private List<ExceptionEventArgs> _channelExceptionRegister;
         private ChannelSession _channel;
-        private Mock<IConnectionInfo> _connectionInfoMock;
-        private MockSequence _sequence;
         private SemaphoreLight _sessionSemaphore;
         private int _initialSessionSemaphoreCount;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
+
             _localChannelNumber = (uint) random.Next(0, int.MaxValue);
             _localWindowSize = (uint) random.Next(0, int.MaxValue);
             _localPacketSize = (uint) random.Next(0, int.MaxValue);
             _remoteChannelNumber = (uint) random.Next(0, int.MaxValue);
             _remoteWindowSize = (uint) random.Next(0, int.MaxValue);
             _remotePacketSize = (uint) random.Next(0, int.MaxValue);
+            _channelCloseTimeout = TimeSpan.FromSeconds(random.Next(10, 20));
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
             _initialSessionSemaphoreCount = random.Next(10, 20);
             _sessionSemaphore = new SemaphoreLight(_initialSessionSemaphoreCount);
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
-            _connectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
+        protected override void SetupMocks()
+        {
+            var sequence = new MockSequence();
 
-            _sequence = new MockSequence();
-            _sessionMock.InSequence(_sequence).Setup(p => p.ConnectionInfo).Returns(_connectionInfoMock.Object);
-            _connectionInfoMock.InSequence(_sequence).Setup(p => p.RetryAttempts).Returns(1);
-            _sessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
-            _sessionMock.InSequence(_sequence)
+            SessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(sequence).Setup(p => p.RetryAttempts).Returns(1);
+            SessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
+            SessionMock.InSequence(sequence)
                 .Setup(
                     p =>
                         p.SendMessage(
@@ -65,12 +59,12 @@ namespace Renci.SshNet.Tests.Classes.Channels
                                     m.LocalChannelNumber == _localChannelNumber &&
                                     m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
                                     m.Info is SessionChannelOpenInfo)));
-            _sessionMock.InSequence(_sequence)
+            SessionMock.InSequence(sequence)
                 .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
                 .Callback<WaitHandle>(
                     w =>
                     {
-                        _sessionMock.Raise(
+                        SessionMock.Raise(
                             s => s.ChannelOpenConfirmationReceived += null,
                             new MessageEventArgs<ChannelOpenConfirmationMessage>(
                                 new ChannelOpenConfirmationMessage(
@@ -80,26 +74,34 @@ namespace Renci.SshNet.Tests.Classes.Channels
                                     _remoteChannelNumber)));
                         w.WaitOne();
                     });
-            _sessionMock.InSequence(_sequence).Setup(p => p.IsConnected).Returns(true);
-            _sessionMock.InSequence(_sequence)
+            SessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
+            SessionMock.InSequence(sequence)
                 .Setup(
                     p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)))
                 .Returns(true);
-            _sessionMock.InSequence(_sequence)
-                .Setup(s => s.WaitOnHandle(It.IsNotNull<EventWaitHandle>()))
-                .Callback<WaitHandle>(w => w.WaitOne());
+            SessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(sequence).Setup(p => p.ChannelCloseTimeout).Returns(_channelCloseTimeout);
+            SessionMock.InSequence(sequence)
+                       .Setup(p => p.TryWait(It.IsNotNull<WaitHandle>(), _channelCloseTimeout))
+                       .Callback<WaitHandle, TimeSpan>((waitHandle, channelCloseTimeout) => waitHandle.WaitOne())
+                       .Returns(WaitResult.Success);
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
 
-            _channel = new ChannelSession(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelSession(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Closed += (sender, args) => _channelClosedRegister.Add(args);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.Open();
 
-            _sessionMock.Raise(
+            SessionMock.Raise(
                 p => p.ChannelCloseReceived += null,
                 new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
         }
 
-        private void Act()
+        protected override void Act()
         {
             _channel.Dispose();
         }

+ 53 - 56
src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_ChannelEofReceived_SendChannelCloseMessageFailure.cs

@@ -10,9 +10,8 @@ using Renci.SshNet.Messages.Connection;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_ChannelEofReceived_SendChannelCloseMessageFailure
+    public class ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_ChannelEofReceived_SendChannelCloseMessageFailure : ChannelSessionTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localChannelNumber;
         private uint _localWindowSize;
         private uint _localPacketSize;
@@ -22,80 +21,78 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private IList<ChannelEventArgs> _channelClosedRegister;
         private List<ExceptionEventArgs> _channelExceptionRegister;
         private ChannelSession _channel;
-        private Mock<IConnectionInfo> _connectionInfoMock;
         private MockSequence _sequence;
         private SemaphoreLight _sessionSemaphore;
         private int _initialSessionSemaphoreCount;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _localWindowSize = (uint)random.Next(0, int.MaxValue);
-            _localPacketSize = (uint)random.Next(0, int.MaxValue);
-            _remoteChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _remoteWindowSize = (uint)random.Next(0, int.MaxValue);
-            _remotePacketSize = (uint)random.Next(0, int.MaxValue);
+
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _localWindowSize = (uint) random.Next(0, int.MaxValue);
+            _localPacketSize = (uint) random.Next(0, int.MaxValue);
+            _remoteChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _remoteWindowSize = (uint) random.Next(0, int.MaxValue);
+            _remotePacketSize = (uint) random.Next(0, int.MaxValue);
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
             _initialSessionSemaphoreCount = random.Next(10, 20);
             _sessionSemaphore = new SemaphoreLight(_initialSessionSemaphoreCount);
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
-            _connectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
-
+        protected override void SetupMocks()
+        {
             _sequence = new MockSequence();
-            _sessionMock.InSequence(_sequence).Setup(p => p.ConnectionInfo).Returns(_connectionInfoMock.Object);
-            _connectionInfoMock.InSequence(_sequence).Setup(p => p.RetryAttempts).Returns(1);
-            _sessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
-            _sessionMock.InSequence(_sequence)
-                .Setup(
-                    p =>
-                        p.SendMessage(
-                            It.Is<ChannelOpenMessage>(
-                                m =>
-                                    m.LocalChannelNumber == _localChannelNumber &&
-                                    m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
-                                    m.Info is SessionChannelOpenInfo)));
-            _sessionMock.InSequence(_sequence)
-                .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
-                .Callback<WaitHandle>(
-                    w =>
-                    {
-                        _sessionMock.Raise(
-                            s => s.ChannelOpenConfirmationReceived += null,
-                            new MessageEventArgs<ChannelOpenConfirmationMessage>(
-                                new ChannelOpenConfirmationMessage(
-                                    _localChannelNumber,
-                                    _remoteWindowSize,
-                                    _remotePacketSize,
-                                    _remoteChannelNumber)));
-                        w.WaitOne();
-                    });
-            _sessionMock.Setup(p => p.IsConnected).Returns(true);
-            _sessionMock.InSequence(_sequence)
-                .Setup(
-                    p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)))
-                .Returns(false);
+            SessionMock.InSequence(_sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(_sequence).Setup(p => p.RetryAttempts).Returns(1);
+            SessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
+            SessionMock.InSequence(_sequence)
+                        .Setup(
+                            p =>
+                                p.SendMessage(
+                                    It.Is<ChannelOpenMessage>(
+                                        m =>
+                                            m.LocalChannelNumber == _localChannelNumber &&
+                                            m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
+                                            m.Info is SessionChannelOpenInfo)));
+            SessionMock.InSequence(_sequence)
+                        .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
+                        .Callback<WaitHandle>(
+                            w =>
+                            {
+                                SessionMock.Raise(
+                                    s => s.ChannelOpenConfirmationReceived += null,
+                                    new MessageEventArgs<ChannelOpenConfirmationMessage>(
+                                        new ChannelOpenConfirmationMessage(
+                                            _localChannelNumber,
+                                            _remoteWindowSize,
+                                            _remotePacketSize,
+                                            _remoteChannelNumber)));
+                                w.WaitOne();
+                            });
+            SessionMock.Setup(p => p.IsConnected).Returns(true);
+            SessionMock.InSequence(_sequence)
+                        .Setup(
+                            p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)))
+                        .Returns(false);
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
 
-            _channel = new ChannelSession(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelSession(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Closed += (sender, args) => _channelClosedRegister.Add(args);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.Open();
 
-            _sessionMock.Raise(
+            SessionMock.Raise(
                 p => p.ChannelEofReceived += null,
                 new MessageEventArgs<ChannelEofMessage>(new ChannelEofMessage(_localChannelNumber)));
         }
 
-        private void Act()
+        protected override void Act()
         {
             _channel.Dispose();
         }
@@ -124,4 +121,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
             Assert.IsFalse(_channel.IsOpen);
         }
     }
-}
+}

+ 38 - 36
src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_ChannelEofReceived_SendChannelCloseMessageSuccess.cs

@@ -10,52 +10,46 @@ using Renci.SshNet.Messages.Connection;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_ChannelEofReceived_SendChannelCloseMessageSuccess
+    public class ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_ChannelEofReceived_SendChannelCloseMessageSuccess : ChannelSessionTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localChannelNumber;
         private uint _localWindowSize;
         private uint _localPacketSize;
         private uint _remoteChannelNumber;
         private uint _remoteWindowSize;
         private uint _remotePacketSize;
+        private TimeSpan _channelCloseTimeout;
         private IList<ChannelEventArgs> _channelClosedRegister;
         private List<ExceptionEventArgs> _channelExceptionRegister;
         private ChannelSession _channel;
-        private Mock<IConnectionInfo> _connectionInfoMock;
-        private MockSequence _sequence;
         private SemaphoreLight _sessionSemaphore;
         private int _initialSessionSemaphoreCount;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
+
             _localChannelNumber = (uint) random.Next(0, int.MaxValue);
             _localWindowSize = (uint) random.Next(0, int.MaxValue);
             _localPacketSize = (uint) random.Next(0, int.MaxValue);
             _remoteChannelNumber = (uint) random.Next(0, int.MaxValue);
             _remoteWindowSize = (uint) random.Next(0, int.MaxValue);
             _remotePacketSize = (uint) random.Next(0, int.MaxValue);
+            _channelCloseTimeout = TimeSpan.FromSeconds(random.Next(10, 20));
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
             _initialSessionSemaphoreCount = random.Next(10, 20);
             _sessionSemaphore = new SemaphoreLight(_initialSessionSemaphoreCount);
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
-            _connectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
+        protected override void SetupMocks()
+        {
+            var sequence = new MockSequence();
 
-            _sequence = new MockSequence();
-            _sessionMock.InSequence(_sequence).Setup(p => p.ConnectionInfo).Returns(_connectionInfoMock.Object);
-            _connectionInfoMock.InSequence(_sequence).Setup(p => p.RetryAttempts).Returns(1);
-            _sessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
-            _sessionMock.InSequence(_sequence)
+            SessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(sequence).Setup(p => p.RetryAttempts).Returns(1);
+            SessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
+            SessionMock.InSequence(sequence)
                 .Setup(
                     p =>
                         p.SendMessage(
@@ -64,12 +58,12 @@ namespace Renci.SshNet.Tests.Classes.Channels
                                     m.LocalChannelNumber == _localChannelNumber &&
                                     m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
                                     m.Info is SessionChannelOpenInfo)));
-            _sessionMock.InSequence(_sequence)
+            SessionMock.InSequence(sequence)
                 .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
                 .Callback<WaitHandle>(
                     w =>
                     {
-                        _sessionMock.Raise(
+                        SessionMock.Raise(
                             s => s.ChannelOpenConfirmationReceived += null,
                             new MessageEventArgs<ChannelOpenConfirmationMessage>(
                                 new ChannelOpenConfirmationMessage(
@@ -79,33 +73,41 @@ namespace Renci.SshNet.Tests.Classes.Channels
                                     _remoteChannelNumber)));
                         w.WaitOne();
                     });
-            _sessionMock.Setup(p => p.IsConnected).Returns(true);
-            _sessionMock.InSequence(_sequence)
+            SessionMock.Setup(p => p.IsConnected).Returns(true);
+            SessionMock.InSequence(sequence)
                 .Setup(
                     p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)))
                 .Returns(true);
-            _sessionMock.InSequence(_sequence)
-                .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
-                .Callback<WaitHandle>(
-                    w =>
-                    {
-                        _sessionMock.Raise(
-                            s => s.ChannelCloseReceived += null,
-                            new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
-                        w.WaitOne();
-                    });
+            SessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(sequence).Setup(p => p.ChannelCloseTimeout).Returns(_channelCloseTimeout);
+            SessionMock.InSequence(sequence)
+                       .Setup(p => p.TryWait(It.IsNotNull<WaitHandle>(), _channelCloseTimeout))
+                       .Callback<WaitHandle, TimeSpan>(
+                           (waitHandle, channelCloseTimeout) =>
+                           {
+                               SessionMock.Raise(
+                                   s => s.ChannelCloseReceived += null,
+                                   new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
+                               waitHandle.WaitOne();
+                           })
+                       .Returns(WaitResult.Success);
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
 
-            _channel = new ChannelSession(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelSession(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Closed += (sender, args) => _channelClosedRegister.Add(args);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.Open();
 
-            _sessionMock.Raise(
+            SessionMock.Raise(
                 p => p.ChannelEofReceived += null,
                 new MessageEventArgs<ChannelEofMessage>(new ChannelEofMessage(_localChannelNumber)));
         }
 
-        private void Act()
+        protected override void Act()
         {
             _channel.Dispose();
         }

+ 74 - 71
src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_NoChannelCloseOrChannelEofReceived.cs

@@ -10,10 +10,8 @@ using Renci.SshNet.Messages.Connection;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_NoChannelCloseOrChannelEofReceived
+    public class ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_NoChannelCloseOrChannelEofReceived : ChannelSessionTestBase
     {
-        private Mock<ISession> _sessionMock;
-        private Mock<IConnectionInfo> _connectionInfoMock;
         private ChannelSession _channel;
         private uint _localChannelNumber;
         private uint _localWindowSize;
@@ -21,89 +19,94 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private uint _remoteWindowSize;
         private uint _remotePacketSize;
         private uint _remoteChannelNumber;
+        private TimeSpan _channelCloseTimeout;
         private SemaphoreLight _sessionSemaphore;
         private IList<ChannelEventArgs> _channelClosedRegister;
         private List<ExceptionEventArgs> _channelExceptionRegister;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _localWindowSize = (uint)random.Next(2000, 3000);
-            _localPacketSize = (uint)random.Next(1000, 2000);
-            _remoteChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _remoteWindowSize = (uint)random.Next(0, int.MaxValue);
-            _remotePacketSize = (uint)random.Next(100, 200);
+
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _localWindowSize = (uint) random.Next(2000, 3000);
+            _localPacketSize = (uint) random.Next(1000, 2000);
+            _remoteChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _remoteWindowSize = (uint) random.Next(0, int.MaxValue);
+            _remotePacketSize = (uint) random.Next(100, 200);
+            _channelCloseTimeout = TimeSpan.FromSeconds(random.Next(10, 20));
             _sessionSemaphore = new SemaphoreLight(1);
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
-            _connectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
-
+        protected override void SetupMocks()
+        {
             var sequence = new MockSequence();
-            _sessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(_connectionInfoMock.Object);
-            _connectionInfoMock.InSequence(sequence).Setup(p => p.RetryAttempts).Returns(1);
-            _sessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
-            _sessionMock.InSequence(sequence)
-                .Setup(
-                    p =>
-                        p.SendMessage(
-                            It.Is<ChannelOpenMessage>(
-                                m =>
-                                    m.LocalChannelNumber == _localChannelNumber &&
-                                    m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
-                                    m.Info is SessionChannelOpenInfo)));
-            _sessionMock.InSequence(sequence)
-                .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
-                .Callback<WaitHandle>(
-                    w =>
-                        {
-                            _sessionMock.Raise(
-                                s => s.ChannelOpenConfirmationReceived += null,
-                                new MessageEventArgs<ChannelOpenConfirmationMessage>(
-                                    new ChannelOpenConfirmationMessage(
-                                        _localChannelNumber,
-                                        _remoteWindowSize,
-                                        _remotePacketSize,
-                                        _remoteChannelNumber)));
-                        w.WaitOne();
-                    });
-            _sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
-            _sessionMock.InSequence(sequence)
-                .Setup(
-                    p => p.TrySendMessage(It.Is<ChannelEofMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)))
-                .Returns(true);
-            _sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
-            _sessionMock.InSequence(sequence)
-                .Setup(
-                    p => p.TrySendMessage(It.Is<ChannelCloseMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)))
-                    .Returns(true);
-            _sessionMock.InSequence(sequence)
-                .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
-                .Callback<WaitHandle>(
-                    w =>
-                    {
-                        _sessionMock.Raise(
-                            s => s.ChannelCloseReceived += null,
-                            new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
-                        w.WaitOne();
-                    });
 
-            _channel = new ChannelSession(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            SessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(sequence).Setup(p => p.RetryAttempts).Returns(1);
+            SessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
+            SessionMock.InSequence(sequence)
+                        .Setup(
+                            p =>
+                                p.SendMessage(
+                                    It.Is<ChannelOpenMessage>(
+                                        m =>
+                                            m.LocalChannelNumber == _localChannelNumber &&
+                                            m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
+                                            m.Info is SessionChannelOpenInfo)));
+            SessionMock.InSequence(sequence)
+                        .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
+                        .Callback<WaitHandle>(
+                            w =>
+                            {
+                                SessionMock.Raise(
+                                    s => s.ChannelOpenConfirmationReceived += null,
+                                    new MessageEventArgs<ChannelOpenConfirmationMessage>(
+                                        new ChannelOpenConfirmationMessage(
+                                            _localChannelNumber,
+                                            _remoteWindowSize,
+                                            _remotePacketSize,
+                                            _remoteChannelNumber)));
+                                w.WaitOne();
+                            });
+            SessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
+            SessionMock.InSequence(sequence)
+                        .Setup(
+                            p => p.TrySendMessage(It.Is<ChannelEofMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)))
+                        .Returns(true);
+            SessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
+            SessionMock.InSequence(sequence)
+                        .Setup(
+                            p => p.TrySendMessage(It.Is<ChannelCloseMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)))
+                        .Returns(true);
+            SessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(sequence).Setup(p => p.ChannelCloseTimeout).Returns(_channelCloseTimeout);
+            SessionMock.InSequence(sequence)
+                       .Setup(p => p.TryWait(It.IsNotNull<WaitHandle>(), _channelCloseTimeout))
+                       .Callback<WaitHandle, TimeSpan>(
+                           (waitHandle, channelCloseTimeout) =>
+                           {
+                               SessionMock.Raise(
+                                   s => s.ChannelCloseReceived += null,
+                                   new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
+                               waitHandle.WaitOne();
+                           })
+                       .Returns(WaitResult.Success);
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
+
+            _channel = new ChannelSession(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Closed += (sender, args) => _channelClosedRegister.Add(args);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.Open();
         }
 
-        private void Act()
+        protected override void Act()
         {
             _channel.Dispose();
         }
@@ -111,13 +114,13 @@ namespace Renci.SshNet.Tests.Classes.Channels
         [TestMethod]
         public void ChannelEofMessageShouldBeSentOnce()
         {
-            _sessionMock.Verify(p => p.TrySendMessage(It.Is<ChannelEofMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)), Times.Once);
+            SessionMock.Verify(p => p.TrySendMessage(It.Is<ChannelEofMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)), Times.Once);
         }
 
         [TestMethod]
         public void ChannelCloseMessageShouldBeSentOnce()
         {
-            _sessionMock.Verify(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)), Times.Once);
+            SessionMock.Verify(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)), Times.Once);
         }
 
         [TestMethod]

+ 73 - 71
src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_NoChannelCloseOrChannelEofReceived_SendChannelEofMessageFailure.cs

@@ -10,10 +10,8 @@ using Renci.SshNet.Messages.Connection;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_NoChannelCloseOrChannelEofReceived_SendChannelEofMessageFailure
+    public class ChannelSessionTest_Dispose_SessionIsConnectedAndChannelIsOpen_NoChannelCloseOrChannelEofReceived_SendChannelEofMessageFailure : ChannelSessionTestBase
     {
-        private Mock<ISession> _sessionMock;
-        private Mock<IConnectionInfo> _connectionInfoMock;
         private ChannelSession _channel;
         private uint _localChannelNumber;
         private uint _localWindowSize;
@@ -21,89 +19,93 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private uint _remoteWindowSize;
         private uint _remotePacketSize;
         private uint _remoteChannelNumber;
+        private TimeSpan _channelCloseTimeout;
         private SemaphoreLight _sessionSemaphore;
         private IList<ChannelEventArgs> _channelClosedRegister;
         private List<ExceptionEventArgs> _channelExceptionRegister;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _localWindowSize = (uint)random.Next(2000, 3000);
-            _localPacketSize = (uint)random.Next(1000, 2000);
-            _remoteChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _remoteWindowSize = (uint)random.Next(0, int.MaxValue);
-            _remotePacketSize = (uint)random.Next(100, 200);
+
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _localWindowSize = (uint) random.Next(2000, 3000);
+            _localPacketSize = (uint) random.Next(1000, 2000);
+            _remoteChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _remoteWindowSize = (uint) random.Next(0, int.MaxValue);
+            _remotePacketSize = (uint) random.Next(100, 200);
+            _channelCloseTimeout = TimeSpan.FromSeconds(random.Next(10, 20));
             _sessionSemaphore = new SemaphoreLight(1);
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
-            _connectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
-
+        protected override void SetupMocks()
+        {
             var sequence = new MockSequence();
-            _sessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(_connectionInfoMock.Object);
-            _connectionInfoMock.InSequence(sequence).Setup(p => p.RetryAttempts).Returns(1);
-            _sessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
-            _sessionMock.InSequence(sequence)
-                .Setup(
-                    p =>
-                        p.SendMessage(
-                            It.Is<ChannelOpenMessage>(
-                                m =>
-                                    m.LocalChannelNumber == _localChannelNumber &&
-                                    m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
-                                    m.Info is SessionChannelOpenInfo)));
-            _sessionMock.InSequence(sequence)
-                .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
-                .Callback<WaitHandle>(
-                    w =>
-                    {
-                        _sessionMock.Raise(
-                            s => s.ChannelOpenConfirmationReceived += null,
-                            new MessageEventArgs<ChannelOpenConfirmationMessage>(
-                                new ChannelOpenConfirmationMessage(
-                                    _localChannelNumber,
-                                    _remoteWindowSize,
-                                    _remotePacketSize,
-                                    _remoteChannelNumber)));
-                        w.WaitOne();
-                    });
-            _sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
-            _sessionMock.InSequence(sequence)
-                .Setup(
-                    p => p.TrySendMessage(It.Is<ChannelEofMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)))
-                .Returns(false);
-            _sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
-            _sessionMock.InSequence(sequence)
-                .Setup(
-                    p => p.TrySendMessage(It.Is<ChannelCloseMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)))
-                .Returns(true);
-            _sessionMock.InSequence(sequence)
-                .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
-                .Callback<WaitHandle>(
-                    w =>
-                    {
-                        _sessionMock.Raise(
-                            s => s.ChannelCloseReceived += null,
-                            new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
-                        w.WaitOne();
-                    });
 
-            _channel = new ChannelSession(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            SessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(sequence).Setup(p => p.RetryAttempts).Returns(1);
+            SessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
+            SessionMock.InSequence(sequence)
+                        .Setup(
+                            p =>
+                                p.SendMessage(
+                                    It.Is<ChannelOpenMessage>(
+                                        m =>
+                                            m.LocalChannelNumber == _localChannelNumber &&
+                                            m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
+                                            m.Info is SessionChannelOpenInfo)));
+            SessionMock.InSequence(sequence)
+                        .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
+                        .Callback<WaitHandle>(
+                            w =>
+                            {
+                                SessionMock.Raise(
+                                    s => s.ChannelOpenConfirmationReceived += null,
+                                    new MessageEventArgs<ChannelOpenConfirmationMessage>(
+                                        new ChannelOpenConfirmationMessage(
+                                            _localChannelNumber,
+                                            _remoteWindowSize,
+                                            _remotePacketSize,
+                                            _remoteChannelNumber)));
+                                w.WaitOne();
+                            });
+            SessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
+            SessionMock.InSequence(sequence)
+                        .Setup(
+                            p => p.TrySendMessage(It.Is<ChannelEofMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)))
+                        .Returns(false);
+            SessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
+            SessionMock.InSequence(sequence)
+                        .Setup(
+                            p => p.TrySendMessage(It.Is<ChannelCloseMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)))
+                        .Returns(true);
+            SessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(sequence).Setup(p => p.ChannelCloseTimeout).Returns(_channelCloseTimeout);
+            SessionMock.InSequence(sequence)
+                       .Setup(p => p.TryWait(It.IsNotNull<WaitHandle>(), _channelCloseTimeout))
+                       .Callback<WaitHandle, TimeSpan>(
+                           (waitHandle, channelCloseTimeout) =>
+                           {
+                               SessionMock.Raise(s => s.ChannelCloseReceived += null,
+                                                 new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
+                               waitHandle.WaitOne();
+                           })
+                       .Returns(WaitResult.Success);
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
+
+            _channel = new ChannelSession(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Closed += (sender, args) => _channelClosedRegister.Add(args);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.Open();
         }
 
-        private void Act()
+        protected override void Act()
         {
             _channel.Dispose();
         }
@@ -111,13 +113,13 @@ namespace Renci.SshNet.Tests.Classes.Channels
         [TestMethod]
         public void ChannelEofMessageShouldBeSentOnce()
         {
-            _sessionMock.Verify(p => p.TrySendMessage(It.Is<ChannelEofMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)), Times.Once);
+            SessionMock.Verify(p => p.TrySendMessage(It.Is<ChannelEofMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)), Times.Once);
         }
 
         [TestMethod]
         public void ChannelCloseMessageShouldBeSentOnce()
         {
-            _sessionMock.Verify(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)), Times.Once);
+            SessionMock.Verify(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)), Times.Once);
         }
 
         [TestMethod]

+ 51 - 53
src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Dispose_SessionIsNotConnectedAndChannelIsOpen_ChannelCloseAndChannelEofReceived.cs

@@ -10,9 +10,8 @@ using Renci.SshNet.Messages.Connection;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelSessionTest_Dispose_SessionIsNotConnectedAndChannelIsOpen_ChannelCloseAndChannelEofReceived
+    public class ChannelSessionTest_Dispose_SessionIsNotConnectedAndChannelIsOpen_ChannelCloseAndChannelEofReceived : ChannelSessionTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localChannelNumber;
         private uint _localWindowSize;
         private uint _localPacketSize;
@@ -22,79 +21,78 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private IList<ChannelEventArgs> _channelClosedRegister;
         private List<ExceptionEventArgs> _channelExceptionRegister;
         private ChannelSession _channel;
-        private Mock<IConnectionInfo> _connectionInfoMock;
         private MockSequence _sequence;
         private SemaphoreLight _sessionSemaphore;
         private int _initialSessionSemaphoreCount;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _localWindowSize = (uint)random.Next(0, int.MaxValue);
-            _localPacketSize = (uint)random.Next(0, int.MaxValue);
-            _remoteChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _remoteWindowSize = (uint)random.Next(0, int.MaxValue);
-            _remotePacketSize = (uint)random.Next(0, int.MaxValue);
+
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _localWindowSize = (uint) random.Next(0, int.MaxValue);
+            _localPacketSize = (uint) random.Next(0, int.MaxValue);
+            _remoteChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _remoteWindowSize = (uint) random.Next(0, int.MaxValue);
+            _remotePacketSize = (uint) random.Next(0, int.MaxValue);
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
             _initialSessionSemaphoreCount = random.Next(10, 20);
             _sessionSemaphore = new SemaphoreLight(_initialSessionSemaphoreCount);
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
-            _connectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
-
+        protected override void SetupMocks()
+        {
             _sequence = new MockSequence();
-            _sessionMock.InSequence(_sequence).Setup(p => p.ConnectionInfo).Returns(_connectionInfoMock.Object);
-            _connectionInfoMock.InSequence(_sequence).Setup(p => p.RetryAttempts).Returns(1);
-            _sessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
-            _sessionMock.InSequence(_sequence)
-                .Setup(
-                    p =>
-                        p.SendMessage(
-                            It.Is<ChannelOpenMessage>(
-                                m =>
-                                    m.LocalChannelNumber == _localChannelNumber &&
-                                    m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
-                                    m.Info is SessionChannelOpenInfo)));
-            _sessionMock.InSequence(_sequence)
-                .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
-                .Callback<WaitHandle>(
-                    w =>
-                    {
-                        _sessionMock.Raise(
-                            s => s.ChannelOpenConfirmationReceived += null,
-                            new MessageEventArgs<ChannelOpenConfirmationMessage>(
-                                new ChannelOpenConfirmationMessage(
-                                    _localChannelNumber,
-                                    _remoteWindowSize,
-                                    _remotePacketSize,
-                                    _remoteChannelNumber)));
-                        w.WaitOne();
-                    });
-            _sessionMock.Setup(p => p.IsConnected).Returns(false);
 
-            _channel = new ChannelSession(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            SessionMock.InSequence(_sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(_sequence).Setup(p => p.RetryAttempts).Returns(1);
+            SessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
+            SessionMock.InSequence(_sequence)
+                        .Setup(
+                            p =>
+                                p.SendMessage(
+                                    It.Is<ChannelOpenMessage>(
+                                        m =>
+                                            m.LocalChannelNumber == _localChannelNumber &&
+                                            m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
+                                            m.Info is SessionChannelOpenInfo)));
+            SessionMock.InSequence(_sequence)
+                        .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
+                        .Callback<WaitHandle>(
+                            w =>
+                            {
+                                SessionMock.Raise(
+                                    s => s.ChannelOpenConfirmationReceived += null,
+                                    new MessageEventArgs<ChannelOpenConfirmationMessage>(
+                                        new ChannelOpenConfirmationMessage(
+                                            _localChannelNumber,
+                                            _remoteWindowSize,
+                                            _remotePacketSize,
+                                            _remoteChannelNumber)));
+                                w.WaitOne();
+                            });
+            SessionMock.Setup(p => p.IsConnected).Returns(false);
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
+
+            _channel = new ChannelSession(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Closed += (sender, args) => _channelClosedRegister.Add(args);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.Open();
 
-            _sessionMock.Raise(
+            SessionMock.Raise(
                 p => p.ChannelEofReceived += null,
                 new MessageEventArgs<ChannelEofMessage>(new ChannelEofMessage(_localChannelNumber)));
-            _sessionMock.Raise(
+            SessionMock.Raise(
                 p => p.ChannelCloseReceived += null,
                 new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
         }
 
-        private void Act()
+        protected override void Act()
         {
             _channel.Dispose();
         }
@@ -124,4 +122,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
             Assert.IsFalse(_channel.IsOpen);
         }
     }
-}
+}

+ 50 - 52
src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Dispose_SessionIsNotConnectedAndChannelIsOpen_ChannelCloseReceived.cs

@@ -10,9 +10,8 @@ using Renci.SshNet.Messages.Connection;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelSessionTest_Dispose_SessionIsNotConnectedAndChannelIsOpen_ChannelCloseReceived
+    public class ChannelSessionTest_Dispose_SessionIsNotConnectedAndChannelIsOpen_ChannelCloseReceived : ChannelSessionTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localChannelNumber;
         private uint _localWindowSize;
         private uint _localPacketSize;
@@ -22,76 +21,75 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private IList<ChannelEventArgs> _channelClosedRegister;
         private List<ExceptionEventArgs> _channelExceptionRegister;
         private ChannelSession _channel;
-        private Mock<IConnectionInfo> _connectionInfoMock;
         private MockSequence _sequence;
         private SemaphoreLight _sessionSemaphore;
         private int _initialSessionSemaphoreCount;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _localWindowSize = (uint)random.Next(0, int.MaxValue);
-            _localPacketSize = (uint)random.Next(0, int.MaxValue);
-            _remoteChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _remoteWindowSize = (uint)random.Next(0, int.MaxValue);
-            _remotePacketSize = (uint)random.Next(0, int.MaxValue);
+
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _localWindowSize = (uint) random.Next(0, int.MaxValue);
+            _localPacketSize = (uint) random.Next(0, int.MaxValue);
+            _remoteChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _remoteWindowSize = (uint) random.Next(0, int.MaxValue);
+            _remotePacketSize = (uint) random.Next(0, int.MaxValue);
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
             _initialSessionSemaphoreCount = random.Next(10, 20);
             _sessionSemaphore = new SemaphoreLight(_initialSessionSemaphoreCount);
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
-            _connectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
-
+        protected override void SetupMocks()
+        {
             _sequence = new MockSequence();
-            _sessionMock.InSequence(_sequence).Setup(p => p.ConnectionInfo).Returns(_connectionInfoMock.Object);
-            _connectionInfoMock.InSequence(_sequence).Setup(p => p.RetryAttempts).Returns(1);
-            _sessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
-            _sessionMock.InSequence(_sequence)
-                .Setup(
-                    p =>
-                        p.SendMessage(
-                            It.Is<ChannelOpenMessage>(
-                                m =>
-                                    m.LocalChannelNumber == _localChannelNumber &&
-                                    m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
-                                    m.Info is SessionChannelOpenInfo)));
-            _sessionMock.InSequence(_sequence)
-                .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
-                .Callback<WaitHandle>(
-                    w =>
-                    {
-                        _sessionMock.Raise(
-                            s => s.ChannelOpenConfirmationReceived += null,
-                            new MessageEventArgs<ChannelOpenConfirmationMessage>(
-                                new ChannelOpenConfirmationMessage(
-                                    _localChannelNumber,
-                                    _remoteWindowSize,
-                                    _remotePacketSize,
-                                    _remoteChannelNumber)));
-                        w.WaitOne();
-                    });
-            _sessionMock.Setup(p => p.IsConnected).Returns(false);
 
-            _channel = new ChannelSession(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            SessionMock.InSequence(_sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(_sequence).Setup(p => p.RetryAttempts).Returns(1);
+            SessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
+            SessionMock.InSequence(_sequence)
+                        .Setup(
+                            p =>
+                                p.SendMessage(
+                                    It.Is<ChannelOpenMessage>(
+                                        m =>
+                                            m.LocalChannelNumber == _localChannelNumber &&
+                                            m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
+                                            m.Info is SessionChannelOpenInfo)));
+            SessionMock.InSequence(_sequence)
+                        .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
+                        .Callback<WaitHandle>(
+                            w =>
+                            {
+                                SessionMock.Raise(
+                                    s => s.ChannelOpenConfirmationReceived += null,
+                                    new MessageEventArgs<ChannelOpenConfirmationMessage>(
+                                        new ChannelOpenConfirmationMessage(
+                                            _localChannelNumber,
+                                            _remoteWindowSize,
+                                            _remotePacketSize,
+                                            _remoteChannelNumber)));
+                                w.WaitOne();
+                            });
+            SessionMock.Setup(p => p.IsConnected).Returns(false);
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
+
+            _channel = new ChannelSession(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Closed += (sender, args) => _channelClosedRegister.Add(args);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.Open();
 
-            _sessionMock.Raise(
+            SessionMock.Raise(
                 p => p.ChannelCloseReceived += null,
                 new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
         }
 
-        private void Act()
+        protected override void Act()
         {
             _channel.Dispose();
         }
@@ -121,4 +119,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
             Assert.IsFalse(_channel.IsOpen);
         }
     }
-}
+}

+ 48 - 51
src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Dispose_SessionIsNotConnectedAndChannelIsOpen_NoChannelCloseOrChannelEofReceived.cs

@@ -10,9 +10,8 @@ using Renci.SshNet.Messages.Connection;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelSessionTest_Dispose_SessionIsNotConnectedAndChannelIsOpen_NoChannelCloseOrChannelEofReceived
+    public class ChannelSessionTest_Dispose_SessionIsNotConnectedAndChannelIsOpen_NoChannelCloseOrChannelEofReceived : ChannelSessionTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localChannelNumber;
         private uint _localWindowSize;
         private uint _localPacketSize;
@@ -22,72 +21,70 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private IList<ChannelEventArgs> _channelClosedRegister;
         private List<ExceptionEventArgs> _channelExceptionRegister;
         private ChannelSession _channel;
-        private Mock<IConnectionInfo> _connectionInfoMock;
         private MockSequence _sequence;
         private SemaphoreLight _sessionSemaphore;
         private int _initialSessionSemaphoreCount;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _localWindowSize = (uint)random.Next(0, int.MaxValue);
-            _localPacketSize = (uint)random.Next(0, int.MaxValue);
-            _remoteChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _remoteWindowSize = (uint)random.Next(0, int.MaxValue);
-            _remotePacketSize = (uint)random.Next(0, int.MaxValue);
+
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _localWindowSize = (uint) random.Next(0, int.MaxValue);
+            _localPacketSize = (uint) random.Next(0, int.MaxValue);
+            _remoteChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _remoteWindowSize = (uint) random.Next(0, int.MaxValue);
+            _remotePacketSize = (uint) random.Next(0, int.MaxValue);
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
             _initialSessionSemaphoreCount = random.Next(10, 20);
             _sessionSemaphore = new SemaphoreLight(_initialSessionSemaphoreCount);
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
-            _connectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
-
+        protected override void SetupMocks()
+        {
             _sequence = new MockSequence();
-            _sessionMock.InSequence(_sequence).Setup(p => p.ConnectionInfo).Returns(_connectionInfoMock.Object);
-            _connectionInfoMock.InSequence(_sequence).Setup(p => p.RetryAttempts).Returns(1);
-            _sessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
-            _sessionMock.InSequence(_sequence)
-                .Setup(
-                    p =>
-                        p.SendMessage(
-                            It.Is<ChannelOpenMessage>(
-                                m =>
-                                    m.LocalChannelNumber == _localChannelNumber &&
-                                    m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
-                                    m.Info is SessionChannelOpenInfo)));
-            _sessionMock.InSequence(_sequence)
-                .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
-                .Callback<WaitHandle>(
-                    w =>
-                    {
-                        _sessionMock.Raise(
-                            s => s.ChannelOpenConfirmationReceived += null,
-                            new MessageEventArgs<ChannelOpenConfirmationMessage>(
-                                new ChannelOpenConfirmationMessage(
-                                    _localChannelNumber,
-                                    _remoteWindowSize,
-                                    _remotePacketSize,
-                                    _remoteChannelNumber)));
-                        w.WaitOne();
-                    });
-            _sessionMock.Setup(p => p.IsConnected).Returns(false);
+            SessionMock.InSequence(_sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(_sequence).Setup(p => p.RetryAttempts).Returns(1);
+            SessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
+            SessionMock.InSequence(_sequence)
+                        .Setup(
+                            p =>
+                                p.SendMessage(
+                                    It.Is<ChannelOpenMessage>(
+                                        m =>
+                                            m.LocalChannelNumber == _localChannelNumber &&
+                                            m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
+                                            m.Info is SessionChannelOpenInfo)));
+            SessionMock.InSequence(_sequence)
+                        .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
+                        .Callback<WaitHandle>(
+                            w =>
+                            {
+                                SessionMock.Raise(
+                                    s => s.ChannelOpenConfirmationReceived += null,
+                                    new MessageEventArgs<ChannelOpenConfirmationMessage>(
+                                        new ChannelOpenConfirmationMessage(
+                                            _localChannelNumber,
+                                            _remoteWindowSize,
+                                            _remotePacketSize,
+                                            _remoteChannelNumber)));
+                                w.WaitOne();
+                            });
+            SessionMock.Setup(p => p.IsConnected).Returns(false);
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
 
-            _channel = new ChannelSession(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelSession(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Closed += (sender, args) => _channelClosedRegister.Add(args);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.Open();
         }
 
-        private void Act()
+        protected override void Act()
         {
             _channel.Dispose();
         }
@@ -116,4 +113,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
             Assert.IsFalse(_channel.IsOpen);
         }
     }
-}
+}

+ 31 - 28
src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_OnSessionChannelCloseReceived_SessionIsConnectedAndChannelIsOpen.cs

@@ -11,52 +11,47 @@ using Renci.SshNet.Tests.Common;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelSessionTest_OnSessionChannelCloseReceived_SessionIsConnectedAndChannelIsOpen
+    public class ChannelSessionTest_OnSessionChannelCloseReceived_SessionIsConnectedAndChannelIsOpen : ChannelSessionTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localChannelNumber;
         private uint _localWindowSize;
         private uint _localPacketSize;
         private uint _remoteChannelNumber;
         private uint _remoteWindowSize;
         private uint _remotePacketSize;
+        private TimeSpan _channelCloseTimeout;
         private IList<ChannelEventArgs> _channelClosedRegister;
         private List<ExceptionEventArgs> _channelExceptionRegister;
         private ChannelSession _channel;
-        private Mock<IConnectionInfo> _connectionInfoMock;
         private MockSequence _sequence;
         private SemaphoreLight _sessionSemaphore;
         private int _initialSessionSemaphoreCount;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
+
             _localChannelNumber = (uint) random.Next(0, int.MaxValue);
             _localWindowSize = (uint) random.Next(0, int.MaxValue);
             _localPacketSize = (uint) random.Next(0, int.MaxValue);
             _remoteChannelNumber = (uint) random.Next(0, int.MaxValue);
             _remoteWindowSize = (uint) random.Next(0, int.MaxValue);
             _remotePacketSize = (uint) random.Next(0, int.MaxValue);
+            _channelCloseTimeout = TimeSpan.FromSeconds(random.Next(10, 20));
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
             _initialSessionSemaphoreCount = random.Next(10, 20);
             _sessionSemaphore = new SemaphoreLight(_initialSessionSemaphoreCount);
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
-            _connectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
-
+        protected override void SetupMocks()
+        {
             _sequence = new MockSequence();
-            _sessionMock.InSequence(_sequence).Setup(p => p.ConnectionInfo).Returns(_connectionInfoMock.Object);
-            _connectionInfoMock.InSequence(_sequence).Setup(p => p.RetryAttempts).Returns(1);
-            _sessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
-            _sessionMock.InSequence(_sequence)
+
+            SessionMock.InSequence(_sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(_sequence).Setup(p => p.RetryAttempts).Returns(1);
+            SessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
+            SessionMock.InSequence(_sequence)
                 .Setup(
                     p =>
                         p.SendMessage(
@@ -65,12 +60,12 @@ namespace Renci.SshNet.Tests.Classes.Channels
                                     m.LocalChannelNumber == _localChannelNumber &&
                                     m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
                                     m.Info is SessionChannelOpenInfo)));
-            _sessionMock.InSequence(_sequence)
+            SessionMock.InSequence(_sequence)
                 .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
                 .Callback<WaitHandle>(
                     w =>
                     {
-                        _sessionMock.Raise(
+                        SessionMock.Raise(
                             s => s.ChannelOpenConfirmationReceived += null,
                             new MessageEventArgs<ChannelOpenConfirmationMessage>(
                                 new ChannelOpenConfirmationMessage(
@@ -80,24 +75,32 @@ namespace Renci.SshNet.Tests.Classes.Channels
                                     _remoteChannelNumber)));
                         w.WaitOne();
                     });
-            _sessionMock.InSequence(_sequence).Setup(p => p.IsConnected).Returns(true);
-            _sessionMock.InSequence(_sequence)
+            SessionMock.InSequence(_sequence).Setup(p => p.IsConnected).Returns(true);
+            SessionMock.InSequence(_sequence)
                 .Setup(
                     p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)))
                 .Returns(true);
-            _sessionMock.InSequence(_sequence)
-                .Setup(s => s.WaitOnHandle(It.IsNotNull<EventWaitHandle>()))
-                .Callback<WaitHandle>(w => w.WaitOne());
+            SessionMock.InSequence(_sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(_sequence).Setup(p => p.ChannelCloseTimeout).Returns(_channelCloseTimeout);
+            SessionMock.InSequence(_sequence)
+                       .Setup(p => p.TryWait(It.IsNotNull<WaitHandle>(), _channelCloseTimeout))
+                       .Callback<WaitHandle, TimeSpan>((waitHandle, channelCloseTimeout) => waitHandle.WaitOne())
+                       .Returns(WaitResult.Success);
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
 
-            _channel = new ChannelSession(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelSession(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Closed += (sender, args) => _channelClosedRegister.Add(args);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.Open();
         }
 
-        private void Act()
+        protected override void Act()
         {
-            _sessionMock.Raise(
+            SessionMock.Raise(
                 p => p.ChannelCloseReceived += null,
                 new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
         }

+ 34 - 35
src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Open_ExceptionWaitingOnOpenConfirmation.cs

@@ -10,10 +10,8 @@ using Renci.SshNet.Messages.Connection;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelSessionTest_Open_ExceptionWaitingOnOpenConfirmation
+    public class ChannelSessionTest_Open_ExceptionWaitingOnOpenConfirmation : ChannelSessionTestBase
     {
-        private Mock<ISession> _sessionMock;
-        private Mock<IConnectionInfo> _connectionInfoMock;
         private ChannelSession _channel;
         private uint _localChannelNumber;
         private uint _localWindowSize;
@@ -25,51 +23,51 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private Exception _waitOnConfirmationException;
         private SystemException _actualException;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _localWindowSize = (uint)random.Next(2000, 3000);
-            _localPacketSize = (uint)random.Next(1000, 2000);
+
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _localWindowSize = (uint) random.Next(2000, 3000);
+            _localPacketSize = (uint) random.Next(1000, 2000);
             _initialSessionSemaphoreCount = random.Next(10, 20);
             _sessionSemaphore = new SemaphoreLight(_initialSessionSemaphoreCount);
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
             _waitOnConfirmationException = new SystemException();
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
-            _connectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
-
+        protected override void SetupMocks()
+        {
             var sequence = new MockSequence();
-            _sessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(_connectionInfoMock.Object);
-            _connectionInfoMock.InSequence(sequence).Setup(p => p.RetryAttempts).Returns(2);
-            _sessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
-            _sessionMock.InSequence(sequence)
-                .Setup(
-                    p =>
-                        p.SendMessage(
-                            It.Is<ChannelOpenMessage>(
-                                m =>
-                                    m.LocalChannelNumber == _localChannelNumber &&
-                                    m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
-                                    m.Info is SessionChannelOpenInfo)));
-            _sessionMock.InSequence(sequence)
-                .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
-                .Throws(_waitOnConfirmationException);
 
-            _channel = new ChannelSession(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            SessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(sequence).Setup(p => p.RetryAttempts).Returns(2);
+            SessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
+            SessionMock.InSequence(sequence)
+                        .Setup(
+                            p =>
+                                p.SendMessage(
+                                    It.Is<ChannelOpenMessage>(
+                                        m =>
+                                            m.LocalChannelNumber == _localChannelNumber &&
+                                            m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
+                                            m.Info is SessionChannelOpenInfo)));
+            SessionMock.InSequence(sequence)
+                        .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
+                        .Throws(_waitOnConfirmationException);
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
+
+            _channel = new ChannelSession(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Closed += (sender, args) => _channelClosedRegister.Add(args);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
         }
 
-        private void Act()
+        protected override void Act()
         {
             try
             {
@@ -84,7 +82,8 @@ namespace Renci.SshNet.Tests.Classes.Channels
         [TestMethod]
         public void OpenShouldHaveRethrownExceptionThrownByWaitOnHandle()
         {
-            
+            Assert.IsNotNull(_actualException);
+            Assert.AreSame(_waitOnConfirmationException, _actualException);
         }
 
         [TestMethod]

+ 22 - 24
src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Open_OnOpenFailureReceived_NoRetriesAvailable.cs

@@ -11,10 +11,8 @@ using Renci.SshNet.Messages.Connection;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelSessionTest_Open_OnOpenFailureReceived_NoRetriesAvailable
+    public class ChannelSessionTest_Open_OnOpenFailureReceived_NoRetriesAvailable : ChannelSessionTestBase
     {
-        private Mock<ISession> _sessionMock;
-        private Mock<IConnectionInfo> _connectionInfoMock;
         private ChannelSession _channel;
         private uint _localChannelNumber;
         private uint _localWindowSize;
@@ -28,16 +26,10 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private string _failureLanguage;
         private SshException _actualException;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
+
             _localChannelNumber = (uint) random.Next(0, int.MaxValue);
             _localWindowSize = (uint) random.Next(2000, 3000);
             _localPacketSize = (uint) random.Next(1000, 2000);
@@ -50,15 +42,16 @@ namespace Renci.SshNet.Tests.Classes.Channels
             _failureReasonCode = (uint)random.Next(0, int.MaxValue);
             _failureDescription = random.Next().ToString(CultureInfo.InvariantCulture);
             _failureLanguage = random.Next().ToString(CultureInfo.InvariantCulture);
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
-            _connectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
-
+        protected override void SetupMocks()
+        {
             var sequence = new MockSequence();
-            _sessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(_connectionInfoMock.Object);
-            _connectionInfoMock.InSequence(sequence).Setup(p => p.RetryAttempts).Returns(1);
-            _sessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
-            _sessionMock.InSequence(sequence)
+
+            SessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(sequence).Setup(p => p.RetryAttempts).Returns(1);
+            SessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
+            SessionMock.InSequence(sequence)
                 .Setup(
                     p =>
                         p.SendMessage(
@@ -67,12 +60,12 @@ namespace Renci.SshNet.Tests.Classes.Channels
                                     m.LocalChannelNumber == _localChannelNumber &&
                                     m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
                                     m.Info is SessionChannelOpenInfo)));
-            _sessionMock.InSequence(sequence)
+            SessionMock.InSequence(sequence)
                 .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
                 .Callback<WaitHandle>(
                     w =>
                         {
-                            _sessionMock.Raise(
+                            SessionMock.Raise(
                                 s => s.ChannelOpenFailureReceived += null,
                                 new MessageEventArgs<ChannelOpenFailureMessage>(
                                     new ChannelOpenFailureMessage(
@@ -83,15 +76,20 @@ namespace Renci.SshNet.Tests.Classes.Channels
                                         )));
                         w.WaitOne();
                     });
-            _sessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(_connectionInfoMock.Object);
-            _connectionInfoMock.InSequence(sequence).Setup(p => p.RetryAttempts).Returns(1);
+            SessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(sequence).Setup(p => p.RetryAttempts).Returns(1);
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
 
-            _channel = new ChannelSession(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelSession(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Closed += (sender, args) => _channelClosedRegister.Add(args);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
         }
 
-        private void Act()
+        protected override void Act()
         {
             try
             {

+ 75 - 77
src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTest_Open_OnOpenFailureReceived_RetriesAvalable.cs

@@ -11,10 +11,8 @@ using Renci.SshNet.Messages.Connection;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelSessionTest_Open_OnOpenFailureReceived_RetriesAvalable
+    public class ChannelSessionTest_Open_OnOpenFailureReceived_RetriesAvalable : ChannelSessionTestBase
     {
-        private Mock<ISession> _sessionMock;
-        private Mock<IConnectionInfo> _connectionInfoMock;
         private ChannelSession _channel;
         private uint _localChannelNumber;
         private uint _localWindowSize;
@@ -30,97 +28,97 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private string _failureDescription;
         private string _failureLanguage;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _localWindowSize = (uint)random.Next(2000, 3000);
-            _localPacketSize = (uint)random.Next(1000, 2000);
-            _remoteChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _remoteWindowSize = (uint)random.Next(0, int.MaxValue);
-            _remotePacketSize = (uint)random.Next(0, int.MaxValue);
+
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _localWindowSize = (uint) random.Next(2000, 3000);
+            _localPacketSize = (uint) random.Next(1000, 2000);
+            _remoteChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _remoteWindowSize = (uint) random.Next(0, int.MaxValue);
+            _remotePacketSize = (uint) random.Next(0, int.MaxValue);
             _initialSessionSemaphoreCount = random.Next(10, 20);
             _sessionSemaphore = new SemaphoreLight(_initialSessionSemaphoreCount);
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
 
-            _failureReasonCode = (uint)random.Next(0, int.MaxValue);
+            _failureReasonCode = (uint) random.Next(0, int.MaxValue);
             _failureDescription = random.Next().ToString(CultureInfo.InvariantCulture);
             _failureLanguage = random.Next().ToString(CultureInfo.InvariantCulture);
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
-            _connectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
-
+        protected override void SetupMocks()
+        {
             var sequence = new MockSequence();
-            _sessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(_connectionInfoMock.Object);
-            _connectionInfoMock.InSequence(sequence).Setup(p => p.RetryAttempts).Returns(2);
-            _sessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
-            _sessionMock.InSequence(sequence)
-                .Setup(
-                    p =>
-                        p.SendMessage(
-                            It.Is<ChannelOpenMessage>(
-                                m =>
-                                    m.LocalChannelNumber == _localChannelNumber &&
-                                    m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
-                                    m.Info is SessionChannelOpenInfo)));
-            _sessionMock.InSequence(sequence)
-                .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
-                .Callback<WaitHandle>(
-                    w =>
-                        {
-                            _sessionMock.Raise(
-                                s => s.ChannelOpenFailureReceived += null,
-                                new MessageEventArgs<ChannelOpenFailureMessage>(
-                                    new ChannelOpenFailureMessage(
-                                        _localChannelNumber,
-                                        _failureDescription,
-                                        _failureReasonCode,
-                                        _failureLanguage
+
+            SessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(sequence).Setup(p => p.RetryAttempts).Returns(2);
+            SessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
+            SessionMock.InSequence(sequence)
+                        .Setup(
+                            p =>
+                                p.SendMessage(
+                                    It.Is<ChannelOpenMessage>(
+                                        m =>
+                                            m.LocalChannelNumber == _localChannelNumber &&
+                                            m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
+                                            m.Info is SessionChannelOpenInfo)));
+            SessionMock.InSequence(sequence)
+                        .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
+                        .Callback<WaitHandle>(
+                            w =>
+                            {
+                                SessionMock.Raise(
+                                    s => s.ChannelOpenFailureReceived += null,
+                                    new MessageEventArgs<ChannelOpenFailureMessage>(
+                                        new ChannelOpenFailureMessage(
+                                            _localChannelNumber,
+                                            _failureDescription,
+                                            _failureReasonCode,
+                                            _failureLanguage
                                         )));
-                        w.WaitOne();
-                    });
-            _sessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(_connectionInfoMock.Object);
-            _connectionInfoMock.InSequence(sequence).Setup(p => p.RetryAttempts).Returns(2);
-            _sessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
-            _sessionMock.InSequence(sequence)
-                .Setup(
-                    p =>
-                        p.SendMessage(
-                            It.Is<ChannelOpenMessage>(
-                                m =>
-                                    m.LocalChannelNumber == _localChannelNumber &&
-                                    m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
-                                    m.Info is SessionChannelOpenInfo)));
-            _sessionMock.InSequence(sequence)
-                .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
-                .Callback<WaitHandle>(
-                    w =>
-                    {
-                        _sessionMock.Raise(
-                            s => s.ChannelOpenConfirmationReceived += null,
-                            new MessageEventArgs<ChannelOpenConfirmationMessage>(
-                                new ChannelOpenConfirmationMessage(
-                                    _localChannelNumber,
-                                    _remoteWindowSize,
-                                    _remotePacketSize,
-                                    _remoteChannelNumber)));
-                        w.WaitOne();
-                    });
+                                w.WaitOne();
+                            });
+            SessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(sequence).Setup(p => p.RetryAttempts).Returns(2);
+            SessionMock.Setup(p => p.SessionSemaphore).Returns(_sessionSemaphore);
+            SessionMock.InSequence(sequence)
+                        .Setup(
+                            p =>
+                                p.SendMessage(
+                                    It.Is<ChannelOpenMessage>(
+                                        m =>
+                                            m.LocalChannelNumber == _localChannelNumber &&
+                                            m.InitialWindowSize == _localWindowSize && m.MaximumPacketSize == _localPacketSize &&
+                                            m.Info is SessionChannelOpenInfo)));
+            SessionMock.InSequence(sequence)
+                        .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
+                        .Callback<WaitHandle>(
+                            w =>
+                            {
+                                SessionMock.Raise(
+                                    s => s.ChannelOpenConfirmationReceived += null,
+                                    new MessageEventArgs<ChannelOpenConfirmationMessage>(
+                                        new ChannelOpenConfirmationMessage(
+                                            _localChannelNumber,
+                                            _remoteWindowSize,
+                                            _remotePacketSize,
+                                            _remoteChannelNumber)));
+                                w.WaitOne();
+                            });
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
 
-            _channel = new ChannelSession(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelSession(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Closed += (sender, args) => _channelClosedRegister.Add(args);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
         }
 
-        private void Act()
+        protected override void Act()
         {
             _channel.Open();
         }

+ 37 - 0
src/Renci.SshNet.Tests/Classes/Channels/ChannelTestBase.cs

@@ -0,0 +1,37 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+
+namespace Renci.SshNet.Tests.Classes.Channels
+{
+    public abstract class ChannelTestBase
+    {
+        internal Mock<ISession> SessionMock { get; private set; }
+        internal Mock<IConnectionInfo> ConnectionInfoMock { get; private set; }
+
+        [TestInitialize]
+        public void Initialize()
+        {
+            Arrange();
+            Act();
+        }
+
+        protected abstract void SetupData();
+
+        protected void CreateMocks()
+        {
+            SessionMock = new Mock<ISession>(MockBehavior.Strict);
+            ConnectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
+        }
+
+        protected abstract void SetupMocks();
+
+        protected virtual void Arrange()
+        {
+            SetupData();
+            CreateMocks();
+            SetupMocks();
+        }
+
+        protected abstract void Act();
+    }
+}

+ 18 - 19
src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_Dispose_SessionIsConnectedAndChannelIsNotOpen.cs

@@ -9,9 +9,8 @@ using Renci.SshNet.Messages;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelTest_Dispose_SessionIsConnectedAndChannelIsNotOpen
+    public class ChannelTest_Dispose_SessionIsConnectedAndChannelIsNotOpen : ChannelTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localWindowSize;
         private uint _localPacketSize;
         private uint _localChannelNumber;
@@ -19,32 +18,32 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private List<ChannelEventArgs> _channelClosedRegister;
         private IList<ExceptionEventArgs> _channelExceptionRegister;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _localWindowSize = (uint)random.Next(0, int.MaxValue);
-            _localPacketSize = (uint)random.Next(0, int.MaxValue);
+
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _localWindowSize = (uint) random.Next(0, int.MaxValue);
+            _localPacketSize = (uint) random.Next(0, int.MaxValue);
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
+        protected override void SetupMocks()
+        {
+            SessionMock.Setup(p => p.IsConnected).Returns(true);
+        }
 
-            _sessionMock.Setup(p => p.IsConnected).Returns(true);
+        protected override void Arrange()
+        {
+            base.Arrange();
 
-            _channel = new ChannelStub(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelStub(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Closed += (sender, args) => _channelClosedRegister.Add(args);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
         }
 
-        private void Act()
+        protected override void Act()
         {
             _channel.Dispose();
         }
@@ -58,7 +57,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
         [TestMethod]
         public void SendMessageOnSessionShouldNeverBeInvoked()
         {
-            _sessionMock.Verify(p => p.SendMessage(It.IsAny<Message>()), Times.Never);
+            SessionMock.Verify(p => p.SendMessage(It.IsAny<Message>()), Times.Never);
         }
 
         [TestMethod]
@@ -73,4 +72,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
             Assert.AreEqual(0, _channelExceptionRegister.Count);
         }
     }
-}
+}

+ 63 - 57
src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_Dispose_SessionIsConnectedAndChannelIsOpen_EofNotReceived.cs

@@ -10,85 +10,91 @@ using Renci.SshNet.Messages.Connection;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelTest_Dispose_SessionIsConnectedAndChannelIsOpen_EofNotReceived
+    public class ChannelTest_Dispose_SessionIsConnectedAndChannelIsOpen_EofNotReceived : ChannelTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localChannelNumber;
         private uint _localWindowSize;
         private uint _localPacketSize;
         private uint _remoteChannelNumber;
         private uint _remoteWindowSize;
         private uint _remotePacketSize;
+        private TimeSpan _channelCloseTimeout;
         private ChannelStub _channel;
         private Stopwatch _closeTimer;
         private ManualResetEvent _channelClosedEventHandlerCompleted;
         private List<ChannelEventArgs> _channelClosedRegister;
         private IList<ExceptionEventArgs> _channelExceptionRegister;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _localWindowSize = (uint)random.Next(0, int.MaxValue);
-            _localPacketSize = (uint)random.Next(0, int.MaxValue);
-            _remoteChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _remoteWindowSize = (uint)random.Next(0, int.MaxValue);
-            _remotePacketSize = (uint)random.Next(0, int.MaxValue);
+
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _localWindowSize = (uint) random.Next(0, int.MaxValue);
+            _localPacketSize = (uint) random.Next(0, int.MaxValue);
+            _remoteChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _remoteWindowSize = (uint) random.Next(0, int.MaxValue);
+            _remotePacketSize = (uint) random.Next(0, int.MaxValue);
+            _channelCloseTimeout = TimeSpan.FromSeconds(random.Next(10, 20));
             _closeTimer = new Stopwatch();
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelClosedEventHandlerCompleted = new ManualResetEvent(false);
             _channelExceptionRegister = new List<ExceptionEventArgs>();
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
-
+        protected override void SetupMocks()
+        {
             var sequence = new MockSequence();
-            _sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
-            _sessionMock.InSequence(sequence).Setup(p => p.TrySendMessage(It.Is<ChannelEofMessage>(c => c.LocalChannelNumber == _remoteChannelNumber))).Returns(true);
-            _sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
-            _sessionMock.InSequence(sequence).Setup(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber))).Returns(true);
-            _sessionMock.InSequence(sequence).Setup(p => p.WaitOnHandle(It.IsAny<EventWaitHandle>()))
-                .Callback<WaitHandle>(w =>
-                    {
-                        new Thread(() =>
-                            {
-                                Thread.Sleep(100);
-                                // raise ChannelCloseReceived event to set waithandle for receiving
-                                // SSH_MSG_CHANNEL_CLOSE message from server which is waited on after
-                                // sending the SSH_MSG_CHANNEL_CLOSE message to the server
-                                _sessionMock.Raise(s => s.ChannelCloseReceived += null,
-                                                   new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
-                            }).Start();
-                        _closeTimer.Start();
-                        try
-                        {
-                            w.WaitOne();
-                        }
-                        finally
-                        {
-                            _closeTimer.Stop();
-                        }
-                    });
-
-            _channel = new ChannelStub(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+
+            SessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
+            SessionMock.InSequence(sequence).Setup(p => p.TrySendMessage(It.Is<ChannelEofMessage>(c => c.LocalChannelNumber == _remoteChannelNumber))).Returns(true);
+            SessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
+            SessionMock.InSequence(sequence).Setup(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber))).Returns(true);
+            SessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(sequence).Setup(p => p.ChannelCloseTimeout).Returns(_channelCloseTimeout);
+            SessionMock.InSequence(sequence)
+                       .Setup(p => p.TryWait(It.IsAny<EventWaitHandle>(), _channelCloseTimeout))
+                       .Callback<WaitHandle, TimeSpan>((waitHandle, channelCloseTimeout) =>
+                       {
+                           new Thread(() =>
+                           {
+                               Thread.Sleep(100);
+                               // raise ChannelCloseReceived event to set waithandle for receiving
+                               // SSH_MSG_CHANNEL_CLOSE message from server which is waited on after
+                               // sending the SSH_MSG_CHANNEL_CLOSE message to the server
+                               SessionMock.Raise(s => s.ChannelCloseReceived += null,
+                                                 new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
+                           }).Start();
+                           _closeTimer.Start();
+                           try
+                           {
+                               waitHandle.WaitOne();
+                           }
+                           finally
+                           {
+                               _closeTimer.Stop();
+                           }
+                       })
+                       .Returns(WaitResult.Success);
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
+
+            _channel = new ChannelStub(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Closed += (sender, args) =>
-                {
-                    _channelClosedRegister.Add(args);
-                    Thread.Sleep(50);
-                    _channelClosedEventHandlerCompleted.Set();
-                };
+            {
+                _channelClosedRegister.Add(args);
+                Thread.Sleep(50);
+                _channelClosedEventHandlerCompleted.Set();
+            };
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.InitializeRemoteChannelInfo(_remoteChannelNumber, _remoteWindowSize, _remotePacketSize);
             _channel.SetIsOpen(true);
         }
 
-        private void Act()
+        protected override void Act()
         {
             _channel.Dispose();
         }
@@ -102,7 +108,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
         [TestMethod]
         public void TrySendMessageOnSessionShouldBeInvokedOnceForChannelCloseMessage()
         {
-            _sessionMock.Verify(
+            SessionMock.Verify(
                 p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)),
                 Times.Once);
         }
@@ -110,15 +116,15 @@ namespace Renci.SshNet.Tests.Classes.Channels
         [TestMethod]
         public void TrySendMessageOnSessionShouldBeInvokedOnceForChannelEofMessage()
         {
-            _sessionMock.Verify(
+            SessionMock.Verify(
                 p => p.TrySendMessage(It.Is<ChannelEofMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)),
                 Times.Once);
         }
 
         [TestMethod]
-        public void WaitOnHandleOnSessionShouldBeInvokedOnce()
+        public void TryWaitOnSessionShouldBeInvokedOnce()
         {
-            _sessionMock.Verify(p => p.WaitOnHandle(It.IsAny<EventWaitHandle>()), Times.Once);
+            SessionMock.Verify(p => p.TryWait(It.IsAny<EventWaitHandle>(), _channelCloseTimeout), Times.Once);
         }
 
         [TestMethod]
@@ -146,4 +152,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
             Assert.AreEqual(0, _channelExceptionRegister.Count);
         }
     }
-}
+}

+ 56 - 56
src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_Dispose_SessionIsConnectedAndChannelIsOpen_EofNotReceived_SendEofInvoked.cs

@@ -11,9 +11,8 @@ namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
     [Ignore]
-    public class ChannelTest_Dispose_SessionIsConnectedAndChannelIsOpen_EofNotReceived_SendEofInvoked
+    public class ChannelTest_Dispose_SessionIsConnectedAndChannelIsOpen_EofNotReceived_SendEofInvoked : ChannelTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localChannelNumber;
         private uint _localWindowSize;
         private uint _localPacketSize;
@@ -26,13 +25,6 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private List<ChannelEventArgs> _channelClosedRegister;
         private IList<ExceptionEventArgs> _channelExceptionRegister;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
         [TestCleanup]
         public void TearDown()
         {
@@ -43,64 +35,72 @@ namespace Renci.SshNet.Tests.Classes.Channels
             }
         }
 
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _localWindowSize = (uint)random.Next(0, int.MaxValue);
-            _localPacketSize = (uint)random.Next(0, int.MaxValue);
-            _remoteChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _remoteWindowSize = (uint)random.Next(0, int.MaxValue);
-            _remotePacketSize = (uint)random.Next(0, int.MaxValue);
+
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _localWindowSize = (uint) random.Next(0, int.MaxValue);
+            _localPacketSize = (uint) random.Next(0, int.MaxValue);
+            _remoteChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _remoteWindowSize = (uint) random.Next(0, int.MaxValue);
+            _remotePacketSize = (uint) random.Next(0, int.MaxValue);
             _closeTimer = new Stopwatch();
             _channelClosedEventHandlerCompleted = new ManualResetEvent(false);
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
-
+        protected override void SetupMocks()
+        {
             var sequence = new MockSequence();
-            _sessionMock.InSequence(sequence).Setup(p => p.SendMessage(It.Is<ChannelEofMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)));
-            _sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
-            _sessionMock.InSequence(sequence).Setup(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber))).Returns(true);
-            _sessionMock.InSequence(sequence).Setup(p => p.WaitOnHandle(It.IsAny<EventWaitHandle>()))
-                .Callback<WaitHandle>(w =>
-                {
-                    new Thread(() =>
-                    {
-                        Thread.Sleep(100);
-                        // raise ChannelCloseReceived event to set waithandle for receiving
-                        // SSH_MSG_CHANNEL_CLOSE message from server which is waited on after
-                        // sending the SSH_MSG_CHANNEL_CLOSE message to the server
-                        _sessionMock.Raise(s => s.ChannelCloseReceived += null,
-                            new MessageEventArgs<ChannelCloseMessage>(
-                                new ChannelCloseMessage(_localChannelNumber)));
-                    }).Start();
-                    _closeTimer.Start();
-                    try
-                    {
-                        w.WaitOne();
-                    }
-                    finally
-                    {
-                        _closeTimer.Stop();
-                    }
-                });
-
-            _channel = new ChannelStub(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+
+            SessionMock.InSequence(sequence).Setup(p => p.SendMessage(It.Is<ChannelEofMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)));
+            SessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
+            SessionMock.InSequence(sequence).Setup(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber))).Returns(true);
+            SessionMock.InSequence(sequence).Setup(p => p.WaitOnHandle(It.IsAny<EventWaitHandle>()))
+                        .Callback<WaitHandle>(w =>
+                        {
+                            new Thread(() =>
+                            {
+                                Thread.Sleep(100);
+                                // raise ChannelCloseReceived event to set waithandle for receiving
+                                // SSH_MSG_CHANNEL_CLOSE message from server which is waited on after
+                                // sending the SSH_MSG_CHANNEL_CLOSE message to the server
+                                SessionMock.Raise(s => s.ChannelCloseReceived += null,
+                                                   new MessageEventArgs<ChannelCloseMessage>(
+                                                       new ChannelCloseMessage(_localChannelNumber)));
+                            }).Start();
+                            _closeTimer.Start();
+                            try
+                            {
+                                w.WaitOne();
+                            }
+                            finally
+                            {
+                                _closeTimer.Stop();
+                            }
+                        });
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
+
+            _channel = new ChannelStub(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Closed += (sender, args) =>
-                {
-                    _channelClosedRegister.Add(args);
-                    Thread.Sleep(50);
-                    _channelClosedEventHandlerCompleted.Set();
-                };
+            {
+                _channelClosedRegister.Add(args);
+                Thread.Sleep(50);
+                _channelClosedEventHandlerCompleted.Set();
+            };
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.InitializeRemoteChannelInfo(_remoteChannelNumber, _remoteWindowSize, _remotePacketSize);
             _channel.SetIsOpen(true);
             //_channel.SendEof();
         }
 
-        private void Act()
+        protected override void Act()
         {
             _channel.Dispose();
         }
@@ -114,7 +114,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
         [TestMethod]
         public void TrySendMessageOnSessionShouldBeInvokedOnceForChannelCloseMessage()
         {
-            _sessionMock.Verify(
+            SessionMock.Verify(
                 p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)),
                 Times.Once);
         }
@@ -122,7 +122,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
         [TestMethod]
         public void SendMessageOnSessionShouldBeInvokedOnceForChannelEofMessage()
         {
-            _sessionMock.Verify(
+            SessionMock.Verify(
                 p => p.SendMessage(It.Is<ChannelEofMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)),
                 Times.Once);
         }
@@ -130,7 +130,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
         [TestMethod]
         public void WaitOnHandleOnSessionShouldBeInvokedOnce()
         {
-            _sessionMock.Verify(p => p.WaitOnHandle(It.IsAny<EventWaitHandle>()), Times.Once);
+            SessionMock.Verify(p => p.WaitOnHandle(It.IsAny<EventWaitHandle>()), Times.Once);
         }
 
         [TestMethod]
@@ -158,4 +158,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
             Assert.AreEqual(0, _channelExceptionRegister.Count);
         }
     }
-}
+}

+ 48 - 57
src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_Dispose_SessionIsConnectedAndChannelIsOpen_EofReceived.cs

@@ -9,15 +9,15 @@ using Renci.SshNet.Messages.Connection;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelTest_Dispose_SessionIsConnectedAndChannelIsOpen_EofReceived
+    public class ChannelTest_Dispose_SessionIsConnectedAndChannelIsOpen_EofReceived : ChannelTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localChannelNumber;
         private uint _localWindowSize;
         private uint _localPacketSize;
         private uint _remoteChannelNumber;
         private uint _remoteWindowSize;
         private uint _remotePacketSize;
+        private TimeSpan _channelCloseTimeout;
         private ChannelStub _channel;
         private List<ChannelEventArgs> _channelClosedRegister;
         private List<ChannelEventArgs> _channelEndOfDataRegister;
@@ -26,7 +26,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private ManualResetEvent _channelClosedEventHandlerCompleted;
         private Thread _raiseChannelCloseReceivedThread;
 
-        private void SetupData()
+        protected override void SetupData()
         {
             var random = new Random();
 
@@ -36,6 +36,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
             _remoteChannelNumber = (uint) random.Next(0, int.MaxValue);
             _remoteWindowSize = (uint) random.Next(0, int.MaxValue);
             _remotePacketSize = (uint) random.Next(0, int.MaxValue);
+            _channelCloseTimeout = TimeSpan.FromSeconds(random.Next(10, 20));
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelEndOfDataRegister = new List<ChannelEventArgs>();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
@@ -44,52 +45,44 @@ namespace Renci.SshNet.Tests.Classes.Channels
             _raiseChannelCloseReceivedThread = null;
         }
 
-        private void CreateMocks()
-        {
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
-        }
-
-        private void SetupMocks()
+        protected override void SetupMocks()
         {
             var sequence = new MockSequence();
 
-            _sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
-            _sessionMock.InSequence(sequence).Setup(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber))).Returns(true);
-            _sessionMock.InSequence(sequence).Setup(p => p.WaitOnHandle(It.IsAny<EventWaitHandle>()))
-                .Callback<WaitHandle>(w =>
-                {
-                    _raiseChannelCloseReceivedThread = new Thread(() =>
-                    {
-                        Thread.Sleep(100);
-
-                        // signal that the ChannelCloseMessage was received; we use this to verify whether we've actually
-                        // waited on the EventWaitHandle to be set; this needs to be set before we raise the ChannelCloseReceived
-                        // to make sure the waithandle is signaled when the Dispose method completes (or else the assert that
-                        // checks whether the handle has been signaled, will sometimes fail)
-                        _channelClosedReceived.Set();
-
-                        // raise ChannelCloseReceived event to set waithandle for receiving SSH_MSG_CHANNEL_CLOSE message
-                        // from server which is waited on after sending the SSH_MSG_CHANNEL_CLOSE message to the server
-                        //
-                        // this will cause a new invocation of Close() that will block until the Close() that was invoked
-                        // as part of Dispose() has released the lock; as such, this thread cannot be joined until that
-                        // lock is released
-                        //
-                        // we're mocking the wait on the ChannelCloseMessage, but we still want
-                        // to get the channel in the state that it would have after actually receiving
-                        // the ChannelCloseMessage
-                        _sessionMock.Raise(s => s.ChannelCloseReceived += null, new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
-                    });
-                    _raiseChannelCloseReceivedThread.Start();
-                    w.WaitOne();
-                });
-        }
-
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
+            SessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
+            SessionMock.InSequence(sequence).Setup(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber))).Returns(true);
+            SessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(sequence).Setup(p => p.ChannelCloseTimeout).Returns(_channelCloseTimeout);
+            SessionMock.InSequence(sequence)
+                       .Setup(p => p.TryWait(It.IsAny<EventWaitHandle>(), _channelCloseTimeout))
+                       .Callback<WaitHandle, TimeSpan>((waitHandle, channelCloseTimeout) =>
+                       {
+                           _raiseChannelCloseReceivedThread = new Thread(() =>
+                           {
+                               Thread.Sleep(100);
+
+                               // signal that the ChannelCloseMessage was received; we use this to verify whether we've actually
+                               // waited on the EventWaitHandle to be set; this needs to be set before we raise the ChannelCloseReceived
+                               // to make sure the waithandle is signaled when the Dispose method completes (or else the assert that
+                               // checks whether the handle has been signaled, will sometimes fail)
+                               _channelClosedReceived.Set();
+
+                               // raise ChannelCloseReceived event to set waithandle for receiving SSH_MSG_CHANNEL_CLOSE message
+                               // from server which is waited on after sending the SSH_MSG_CHANNEL_CLOSE message to the server
+                               //
+                               // this will cause a new invocation of Close() that will block until the Close() that was invoked
+                               // as part of Dispose() has released the lock; as such, this thread cannot be joined until that
+                               // lock is released
+                               //
+                               // we're mocking the wait on the ChannelCloseMessage, but we still want
+                               // to get the channel in the state that it would have after actually receiving
+                               // the ChannelCloseMessage
+                               SessionMock.Raise(s => s.ChannelCloseReceived += null, new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
+                           });
+                           _raiseChannelCloseReceivedThread.Start();
+                           waitHandle.WaitOne();
+                       })
+                       .Returns(WaitResult.Success);
         }
 
         [TestCleanup]
@@ -116,13 +109,11 @@ namespace Renci.SshNet.Tests.Classes.Channels
             }
         }
 
-        private void Arrange()
+        protected override void Arrange()
         {
-            SetupData();
-            CreateMocks();
-            SetupMocks();
+            base.Arrange();
 
-            _channel = new ChannelStub(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelStub(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Closed += (sender, args) =>
                 {
                     _channelClosedRegister.Add(args);
@@ -134,12 +125,12 @@ namespace Renci.SshNet.Tests.Classes.Channels
             _channel.InitializeRemoteChannelInfo(_remoteChannelNumber, _remoteWindowSize, _remotePacketSize);
             _channel.SetIsOpen(true);
 
-            _sessionMock.Raise(
+            SessionMock.Raise(
                 s => s.ChannelEofReceived += null,
                 new MessageEventArgs<ChannelEofMessage>(new ChannelEofMessage(_localChannelNumber)));
         }
 
-        private void Act()
+        protected override void Act()
         {
             _channel.Dispose();
         }
@@ -153,7 +144,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
         [TestMethod]
         public void TrySendMessageOnSessionShouldBeInvokedOnceForChannelCloseMessage()
         {
-            _sessionMock.Verify(
+            SessionMock.Verify(
                 p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)),
                 Times.Once);
         }
@@ -161,15 +152,15 @@ namespace Renci.SshNet.Tests.Classes.Channels
         [TestMethod]
         public void TrySendMessageOnSessionShouldNeverBeInvokedForChannelEofMessage()
         {
-            _sessionMock.Verify(
+            SessionMock.Verify(
                 p => p.TrySendMessage(It.Is<ChannelEofMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)),
                 Times.Never);
         }
 
         [TestMethod]
-        public void WaitOnHandleOnSessionShouldBeInvokedOnce()
+        public void TryWaitOnSessionShouldBeInvokedOnce()
         {
-            _sessionMock.Verify(p => p.WaitOnHandle(It.IsAny<EventWaitHandle>()), Times.Once);
+            SessionMock.Verify(p => p.TryWait(It.IsAny<EventWaitHandle>(), _channelCloseTimeout), Times.Once);
         }
 
         [TestMethod]

+ 27 - 47
src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_Dispose_SessionIsConnectedAndChannelIsOpen_EofReceived_ConnectionExceptionWaitingForChannelCloseMessage.cs → src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_Dispose_SessionIsConnectedAndChannelIsOpen_EofReceived_DisconnectWaitingForChannelCloseMessage.cs

@@ -9,84 +9,64 @@ using Renci.SshNet.Messages.Connection;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelTest_Dispose_SessionIsConnectedAndChannelIsOpen_EofReceived_ConnectionExceptionWaitingForChannelCloseMessage
+    public class ChannelTest_Dispose_SessionIsConnectedAndChannelIsOpen_EofReceived_DisconnectWaitingForChannelCloseMessage : ChannelTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localChannelNumber;
         private uint _localWindowSize;
         private uint _localPacketSize;
         private uint _remoteChannelNumber;
         private uint _remoteWindowSize;
         private uint _remotePacketSize;
+        private TimeSpan _channelCloseTimeout;
         private ChannelStub _channel;
         private List<ChannelEventArgs> _channelClosedRegister;
         private List<ChannelEventArgs> _channelEndOfDataRegister;
         private IList<ExceptionEventArgs> _channelExceptionRegister;
-        private SshConnectionException _connectionException;
 
-        private void SetupData()
+        protected override void SetupData()
         {
             var random = new Random();
 
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _localWindowSize = (uint)random.Next(0, int.MaxValue);
-            _localPacketSize = (uint)random.Next(0, int.MaxValue);
-            _remoteChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _remoteWindowSize = (uint)random.Next(0, int.MaxValue);
-            _remotePacketSize = (uint)random.Next(0, int.MaxValue);
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _localWindowSize = (uint) random.Next(0, int.MaxValue);
+            _localPacketSize = (uint) random.Next(0, int.MaxValue);
+            _remoteChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _remoteWindowSize = (uint) random.Next(0, int.MaxValue);
+            _remotePacketSize = (uint) random.Next(0, int.MaxValue);
+            _channelCloseTimeout = TimeSpan.FromSeconds(random.Next(10, 20));
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelEndOfDataRegister = new List<ChannelEventArgs>();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
-            _connectionException = new SshConnectionException();
         }
 
-        private void CreateMocks()
-        {
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
-        }
-
-        private void SetupMocks()
+        protected override void SetupMocks()
         {
             var sequence = new MockSequence();
 
-            _sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
-            _sessionMock.InSequence(sequence).Setup(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber))).Returns(true);
-            _sessionMock.InSequence(sequence).Setup(p => p.WaitOnHandle(It.IsAny<EventWaitHandle>()))
-                .Callback<WaitHandle>(w =>
-                {
-                    throw _connectionException;
-                });
+            SessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
+            SessionMock.InSequence(sequence).Setup(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber))).Returns(true);
+            SessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(sequence).Setup(p => p.ChannelCloseTimeout).Returns(_channelCloseTimeout);
+            SessionMock.InSequence(sequence).Setup(p => p.TryWait(It.IsAny<EventWaitHandle>(), _channelCloseTimeout)).Returns(WaitResult.Disconnected);
         }
 
-        [TestInitialize]
-        public void Initialize()
+        protected override void Arrange()
         {
-            Arrange();
-            Act();
-        }
+            base.Arrange();
 
-        private void Arrange()
-        {
-            SetupData();
-            CreateMocks();
-            SetupMocks();
-
-            _channel = new ChannelStub(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
-            _channel.Closed += (sender, args) =>
-            {
-                _channelClosedRegister.Add(args);
-            };
+            _channel = new ChannelStub(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel.Closed += (sender, args) => { _channelClosedRegister.Add(args); };
             _channel.EndOfData += (sender, args) => _channelEndOfDataRegister.Add(args);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.InitializeRemoteChannelInfo(_remoteChannelNumber, _remoteWindowSize, _remotePacketSize);
             _channel.SetIsOpen(true);
 
-            _sessionMock.Raise(
+            SessionMock.Raise(
                 s => s.ChannelEofReceived += null,
                 new MessageEventArgs<ChannelEofMessage>(new ChannelEofMessage(_localChannelNumber)));
         }
 
-        private void Act()
+        protected override void Act()
         {
             _channel.Dispose();
         }
@@ -100,7 +80,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
         [TestMethod]
         public void TrySendMessageOnSessionShouldBeInvokedOnceForChannelCloseMessage()
         {
-            _sessionMock.Verify(
+            SessionMock.Verify(
                 p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)),
                 Times.Once);
         }
@@ -108,15 +88,15 @@ namespace Renci.SshNet.Tests.Classes.Channels
         [TestMethod]
         public void TrySendMessageOnSessionShouldNeverBeInvokedForChannelEofMessage()
         {
-            _sessionMock.Verify(
+            SessionMock.Verify(
                 p => p.TrySendMessage(It.Is<ChannelEofMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)),
                 Times.Never);
         }
 
         [TestMethod]
-        public void WaitOnHandleOnSessionShouldBeInvokedOnce()
+        public void TryWaitOnSessionShouldBeInvokedOnce()
         {
-            _sessionMock.Verify(p => p.WaitOnHandle(It.IsAny<EventWaitHandle>()), Times.Once);
+            SessionMock.Verify(p => p.TryWait(It.IsAny<EventWaitHandle>(), _channelCloseTimeout), Times.Once);
         }
 
         [TestMethod]
@@ -138,4 +118,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
             Assert.AreEqual(0, _channelExceptionRegister.Count);
         }
     }
-}
+}

+ 30 - 66
src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_Dispose_SessionIsConnectedAndChannelIsOpen_EofReceived_OperationTimeoutExceptionWaitingForChannelCloseMessage.cs → src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_Dispose_SessionIsConnectedAndChannelIsOpen_EofReceived_TimeoutWaitingForChannelCloseMessage.cs

@@ -9,107 +9,78 @@ using Renci.SshNet.Messages.Connection;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelTest_Dispose_SessionIsConnectedAndChannelIsOpen_EofReceived_OperationTimeoutExceptionWaitingForChannelCloseMessage
+    public class ChannelTest_Dispose_SessionIsConnectedAndChannelIsOpen_EofReceived_TimeoutWaitingForChannelCloseMessage : ChannelTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localChannelNumber;
         private uint _localWindowSize;
         private uint _localPacketSize;
         private uint _remoteChannelNumber;
         private uint _remoteWindowSize;
         private uint _remotePacketSize;
+        private TimeSpan _channelCloseTimeout;
         private ChannelStub _channel;
         private List<ChannelEventArgs> _channelClosedRegister;
         private List<ChannelEventArgs> _channelEndOfDataRegister;
         private IList<ExceptionEventArgs> _channelExceptionRegister;
-        private SshOperationTimeoutException _operationTimeoutException;
-        private SshOperationTimeoutException _actualException;
 
-        private void SetupData()
+        protected override void SetupData()
         {
             var random = new Random();
 
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _localWindowSize = (uint)random.Next(0, int.MaxValue);
-            _localPacketSize = (uint)random.Next(0, int.MaxValue);
-            _remoteChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _remoteWindowSize = (uint)random.Next(0, int.MaxValue);
-            _remotePacketSize = (uint)random.Next(0, int.MaxValue);
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _localWindowSize = (uint) random.Next(0, int.MaxValue);
+            _localPacketSize = (uint) random.Next(0, int.MaxValue);
+            _remoteChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _remoteWindowSize = (uint) random.Next(0, int.MaxValue);
+            _remotePacketSize = (uint) random.Next(0, int.MaxValue);
+            _channelCloseTimeout = TimeSpan.FromSeconds(random.Next());
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelEndOfDataRegister = new List<ChannelEventArgs>();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
-            _operationTimeoutException = new SshOperationTimeoutException();
-            _actualException = null;
         }
 
-        private void CreateMocks()
-        {
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
-        }
-
-        private void SetupMocks()
+        protected override void SetupMocks()
         {
             var sequence = new MockSequence();
 
-            _sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
-            _sessionMock.InSequence(sequence).Setup(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber))).Returns(true);
-            _sessionMock.InSequence(sequence).Setup(p => p.WaitOnHandle(It.IsAny<EventWaitHandle>()))
-                .Callback<WaitHandle>(w =>
-                {
-                    throw _operationTimeoutException;
-                });
+            SessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
+            SessionMock.InSequence(sequence).Setup(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber))).Returns(true);
+            SessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(sequence).Setup(p => p.ChannelCloseTimeout).Returns(_channelCloseTimeout);
+            SessionMock.InSequence(sequence).Setup(p => p.TryWait(It.IsAny<EventWaitHandle>(), _channelCloseTimeout)).Returns(WaitResult.TimedOut);
         }
 
-        [TestInitialize]
-        public void Initialize()
+        protected override void Arrange()
         {
-            Arrange();
-            Act();
-        }
+            base.Arrange();
 
-        private void Arrange()
-        {
-            SetupData();
-            CreateMocks();
-            SetupMocks();
-
-            _channel = new ChannelStub(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
-            _channel.Closed += (sender, args) =>
-                {
-                    _channelClosedRegister.Add(args);
-                };
+            _channel = new ChannelStub(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel.Closed += (sender, args) => { _channelClosedRegister.Add(args); };
             _channel.EndOfData += (sender, args) => _channelEndOfDataRegister.Add(args);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.InitializeRemoteChannelInfo(_remoteChannelNumber, _remoteWindowSize, _remotePacketSize);
             _channel.SetIsOpen(true);
 
-            _sessionMock.Raise(
+            SessionMock.Raise(
                 s => s.ChannelEofReceived += null,
                 new MessageEventArgs<ChannelEofMessage>(new ChannelEofMessage(_localChannelNumber)));
         }
 
-        private void Act()
+        protected override void Act()
         {
-            try
-            {
-                _channel.Dispose();
-            }
-            catch (SshOperationTimeoutException ex)
-            {
-                _actualException = ex;
-            }
+            _channel.Dispose();
         }
 
         [TestMethod]
-        public void IsOpenShouldReturnTrue()
+        public void IsOpenShouldReturnFalse()
         {
-            Assert.IsTrue(_channel.IsOpen);
+            Assert.IsFalse(_channel.IsOpen);
         }
 
         [TestMethod]
         public void TrySendMessageOnSessionShouldBeInvokedOnceForChannelCloseMessage()
         {
-            _sessionMock.Verify(
+            SessionMock.Verify(
                 p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)),
                 Times.Once);
         }
@@ -117,15 +88,15 @@ namespace Renci.SshNet.Tests.Classes.Channels
         [TestMethod]
         public void TrySendMessageOnSessionShouldNeverBeInvokedForChannelEofMessage()
         {
-            _sessionMock.Verify(
+            SessionMock.Verify(
                 p => p.TrySendMessage(It.Is<ChannelEofMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)),
                 Times.Never);
         }
 
         [TestMethod]
-        public void WaitOnHandleOnSessionShouldBeInvokedOnce()
+        public void TryWaitOnSessionShouldBeInvokedOnce()
         {
-            _sessionMock.Verify(p => p.WaitOnHandle(It.IsAny<EventWaitHandle>()), Times.Once);
+            SessionMock.Verify(p => p.TryWait(It.IsAny<EventWaitHandle>(), _channelCloseTimeout), Times.Once);
         }
 
         [TestMethod]
@@ -146,12 +117,5 @@ namespace Renci.SshNet.Tests.Classes.Channels
         {
             Assert.AreEqual(0, _channelExceptionRegister.Count);
         }
-
-        [TestMethod]
-        public void DisposeShouldHaveThrownOperationTimeoutException()
-        {
-            Assert.IsNotNull(_actualException);
-            Assert.AreSame(_operationTimeoutException, _actualException);
-        }
     }
-}
+}

+ 16 - 17
src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_Dispose_SessionIsNotConnectedAndChannelIsNotOpen.cs

@@ -9,9 +9,8 @@ using Renci.SshNet.Messages;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelTest_Dispose_SessionIsNotConnectedAndChannelIsNotOpen
+    public class ChannelTest_Dispose_SessionIsNotConnectedAndChannelIsNotOpen : ChannelTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localWindowSize;
         private uint _localPacketSize;
         private uint _localChannelNumber;
@@ -19,32 +18,32 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private List<ChannelEventArgs> _channelClosedRegister;
         private IList<ExceptionEventArgs> _channelExceptionRegister;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
+
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
             _localWindowSize = (uint) random.Next(0, int.MaxValue);
             _localPacketSize = (uint) random.Next(0, int.MaxValue);
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
+        protected override void SetupMocks()
+        {
+            SessionMock.Setup(p => p.IsConnected).Returns(false);
+        }
 
-            _sessionMock.Setup(p => p.IsConnected).Returns(false);
+        protected override void Arrange()
+        {
+            base.Arrange();
 
-            _channel = new ChannelStub(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelStub(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Closed += (sender, args) => _channelClosedRegister.Add(args);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
         }
 
-        private void Act()
+        protected override void Act()
         {
             _channel.Dispose();
         }
@@ -58,7 +57,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
         [TestMethod]
         public void SendMessageOnSessionShouldNeverBeInvoked()
         {
-            _sessionMock.Verify(p => p.SendMessage(It.IsAny<Message>()), Times.Never);
+            SessionMock.Verify(p => p.SendMessage(It.IsAny<Message>()), Times.Never);
         }
 
         [TestMethod]
@@ -73,4 +72,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
             Assert.AreEqual(0, _channelExceptionRegister.Count);
         }
     }
-}
+}

+ 18 - 19
src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_Dispose_SessionIsNotConnectedAndChannelIsOpen.cs

@@ -8,9 +8,8 @@ using Renci.SshNet.Messages;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelTest_Dispose_SessionIsNotConnectedAndChannelIsOpen
+    public class ChannelTest_Dispose_SessionIsNotConnectedAndChannelIsOpen : ChannelTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localWindowSize;
         private uint _localPacketSize;
         private uint _localChannelNumber;
@@ -18,33 +17,33 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private List<ChannelEventArgs> _channelClosedRegister;
         private IList<ExceptionEventArgs> _channelExceptionRegister;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _localWindowSize = (uint)random.Next(0, int.MaxValue);
-            _localPacketSize = (uint)random.Next(0, int.MaxValue);
+
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _localWindowSize = (uint) random.Next(0, int.MaxValue);
+            _localPacketSize = (uint) random.Next(0, int.MaxValue);
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
+        protected override void SetupMocks()
+        {
+            SessionMock.Setup(p => p.IsConnected).Returns(false);
+        }
 
-            _sessionMock.Setup(p => p.IsConnected).Returns(false);
+        protected override void Arrange()
+        {
+            base.Arrange();
 
-            _channel = new ChannelStub(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelStub(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Closed += (sender, args) => _channelClosedRegister.Add(args);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.SetIsOpen(true);
         }
 
-        private void Act()
+        protected override void Act()
         {
             _channel.Dispose();
         }
@@ -58,7 +57,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
         [TestMethod]
         public void SendMessageOnSessionShouldNeverBeInvoked()
         {
-            _sessionMock.Verify(p => p.SendMessage(It.IsAny<Message>()), Times.Never);
+            SessionMock.Verify(p => p.SendMessage(It.IsAny<Message>()), Times.Never);
         }
 
         [TestMethod]
@@ -73,4 +72,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
             Assert.AreEqual(0, _channelExceptionRegister.Count);
         }
     }
-}
+}

+ 14 - 14
src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_OnSessionChannelCloseReceived_OnClose_Exception.cs

@@ -8,9 +8,8 @@ using Renci.SshNet.Messages.Connection;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelTest_OnSessionChannelCloseReceived_OnClose_Exception
+    public class ChannelTest_OnSessionChannelCloseReceived_OnClose_Exception : ChannelTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localWindowSize;
         private uint _localPacketSize;
         private uint _localChannelNumber;
@@ -18,32 +17,33 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private IList<ExceptionEventArgs> _channelExceptionRegister;
         private Exception _onCloseException;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
+
             _localWindowSize = (uint) random.Next(1000, int.MaxValue);
             _localPacketSize = _localWindowSize - 1;
             _localChannelNumber = (uint) random.Next(0, int.MaxValue);
             _onCloseException = new SystemException();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
+        protected override void SetupMocks()
+        {
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
 
-            _channel = new ChannelStub(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelStub(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.OnCloseException = _onCloseException;
         }
 
-        private void Act()
+        protected override void Act()
         {
-            _sessionMock.Raise(s => s.ChannelCloseReceived += null,
+            SessionMock.Raise(s => s.ChannelCloseReceived += null,
                 new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
         }
 

+ 30 - 34
src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_OnSessionChannelCloseReceived_SessionIsConnectedAndChannelIsOpen_DisposeChannelInClosedEventHandler.cs

@@ -9,22 +9,23 @@ using Renci.SshNet.Messages.Connection;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelTest_OnSessionChannelCloseReceived_SessionIsConnectedAndChannelIsOpen_DisposeChannelInClosedEventHandler
+    public class ChannelTest_OnSessionChannelCloseReceived_SessionIsConnectedAndChannelIsOpen_DisposeChannelInClosedEventHandler : ChannelTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localChannelNumber;
         private uint _localWindowSize;
         private uint _localPacketSize;
         private uint _remoteChannelNumber;
         private uint _remoteWindowSize;
         private uint _remotePacketSize;
+        private TimeSpan _channelCloseTimeout;
         private ChannelStub _channel;
         private List<ChannelEventArgs> _channelClosedRegister;
         private List<ChannelEventArgs> _channelEndOfDataRegister;
         private IList<ExceptionEventArgs> _channelExceptionRegister;
         private ManualResetEvent _channelClosedEventHandlerCompleted;
+        private bool _channelClosedWaitHandleSignaled;
 
-        private void SetupData()
+        protected override void SetupData()
         {
             var random = new Random();
 
@@ -34,44 +35,33 @@ namespace Renci.SshNet.Tests.Classes.Channels
             _remoteChannelNumber = (uint) random.Next(0, int.MaxValue);
             _remoteWindowSize = (uint) random.Next(0, int.MaxValue);
             _remotePacketSize = (uint) random.Next(0, int.MaxValue);
+            _channelCloseTimeout = TimeSpan.FromSeconds(random.Next(10, 20));
+            _channelClosedWaitHandleSignaled = false;
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelEndOfDataRegister = new List<ChannelEventArgs>();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
             _channelClosedEventHandlerCompleted = new ManualResetEvent(false);
         }
 
-        private void CreateMocks()
-        {
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
-        }
-
-        private void SetupMocks()
+        protected override void SetupMocks()
         {
             var sequence = new MockSequence();
 
-            _sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
-            _sessionMock.InSequence(sequence)
-                        .Setup(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)))
-                        .Returns(true);
-            _sessionMock.InSequence(sequence)
-                        .Setup(p => p.WaitOnHandle(It.IsAny<EventWaitHandle>()))
-                        .Callback<WaitHandle>(w => w.WaitOne());
-        }
-
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
+            SessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
+            SessionMock.InSequence(sequence).Setup(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber))).Returns(true);
+            SessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(sequence).Setup(p => p.ChannelCloseTimeout).Returns(_channelCloseTimeout);
+            SessionMock.InSequence(sequence)
+                        .Setup(p => p.TryWait(It.IsAny<EventWaitHandle>(), _channelCloseTimeout))
+                        .Callback<WaitHandle, TimeSpan>((waitHandle, channelCloseTimeout) => _channelClosedWaitHandleSignaled = waitHandle.WaitOne(0))
+                        .Returns(WaitResult.Success);
         }
 
-        private void Arrange()
+        protected override void Arrange()
         {
-            SetupData();
-            CreateMocks();
-            SetupMocks();
+            base.Arrange();
 
-            _channel = new ChannelStub(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelStub(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Closed += (sender, args) =>
                 {
                     _channelClosedRegister.Add(args);
@@ -84,9 +74,9 @@ namespace Renci.SshNet.Tests.Classes.Channels
             _channel.SetIsOpen(true);
         }
 
-        private void Act()
+        protected override void Act()
         {
-            _sessionMock.Raise(
+            SessionMock.Raise(
                 s => s.ChannelCloseReceived += null,
                 new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
         }
@@ -100,7 +90,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
         [TestMethod]
         public void TrySendMessageOnSessionShouldBeInvokedOnceForChannelCloseMessage()
         {
-            _sessionMock.Verify(
+            SessionMock.Verify(
                 p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)),
                 Times.Once);
         }
@@ -108,15 +98,21 @@ namespace Renci.SshNet.Tests.Classes.Channels
         [TestMethod]
         public void TrySendMessageOnSessionShouldNeverBeInvokedForChannelEofMessage()
         {
-            _sessionMock.Verify(
+            SessionMock.Verify(
                 p => p.TrySendMessage(It.Is<ChannelEofMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)),
                 Times.Never);
         }
 
         [TestMethod]
-        public void WaitOnHandleOnSessionShouldBeInvokedOnce()
+        public void TryWaitOnSessionShouldBeInvokedOnce()
+        {
+            SessionMock.Verify(p => p.TryWait(It.IsAny<EventWaitHandle>(), _channelCloseTimeout), Times.Once);
+        }
+
+        [TestMethod]
+        public void ChannelCloseWaitHandleShouldHaveBeenSignaledImmediately()
         {
-            _sessionMock.Verify(p => p.WaitOnHandle(It.IsAny<EventWaitHandle>()), Times.Once);
+            Assert.IsTrue(_channelClosedWaitHandleSignaled);
         }
 
         [TestMethod]

+ 34 - 30
src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_OnSessionChannelCloseReceived_SessionIsConnectedAndChannelIsOpen_EofNotReceived.cs

@@ -10,51 +10,55 @@ using Renci.SshNet.Tests.Common;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelTest_OnSessionChannelCloseReceived_SessionIsConnectedAndChannelIsOpen_EofNotReceived
+    public class ChannelTest_OnSessionChannelCloseReceived_SessionIsConnectedAndChannelIsOpen_EofNotReceived : ChannelTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localChannelNumber;
         private uint _localWindowSize;
         private uint _localPacketSize;
         private uint _remoteChannelNumber;
         private uint _remoteWindowSize;
         private uint _remotePacketSize;
+        private TimeSpan _channelCloseTimeout;
         private IList<ChannelEventArgs> _channelClosedRegister;
         private IList<ExceptionEventArgs> _channelExceptionRegister;
         private ManualResetEvent _channelClosedEventHandlerCompleted;
         private ChannelStub _channel;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _localWindowSize = (uint)random.Next(0, int.MaxValue);
-            _localPacketSize = (uint)random.Next(0, int.MaxValue);
-            _remoteChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _remoteWindowSize = (uint)random.Next(0, int.MaxValue);
-            _remotePacketSize = (uint)random.Next(0, int.MaxValue);
+
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _localWindowSize = (uint) random.Next(0, int.MaxValue);
+            _localPacketSize = (uint) random.Next(0, int.MaxValue);
+            _remoteChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _remoteWindowSize = (uint) random.Next(0, int.MaxValue);
+            _remotePacketSize = (uint) random.Next(0, int.MaxValue);
+            _channelCloseTimeout = TimeSpan.FromSeconds(random.Next(10, 20));
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
             _channelClosedEventHandlerCompleted = new ManualResetEvent(false);
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
-
+        protected override void SetupMocks()
+        {
             var sequence = new MockSequence();
 
-            _sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
-            _sessionMock.InSequence(sequence).Setup(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber))).Returns(true);
-            _sessionMock.InSequence(sequence)
-                .Setup(s => s.WaitOnHandle(It.IsNotNull<EventWaitHandle>()))
-                .Callback<WaitHandle>(w => w.WaitOne());
+            SessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
+            SessionMock.InSequence(sequence).Setup(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber))).Returns(true);
+            SessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(sequence).Setup(p => p.ChannelCloseTimeout).Returns(_channelCloseTimeout);
+            SessionMock.InSequence(sequence)
+                        .Setup(p => p.TryWait(It.IsAny<EventWaitHandle>(), _channelCloseTimeout))
+                        .Callback<WaitHandle, TimeSpan>((waitHandle, channelCloseTimeout) => waitHandle.WaitOne())
+                        .Returns(WaitResult.Success);
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
 
-            _channel = new ChannelStub(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelStub(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Closed += (sender, args) =>
                 {
                     _channelClosedRegister.Add(args);
@@ -66,9 +70,9 @@ namespace Renci.SshNet.Tests.Classes.Channels
             _channel.SetIsOpen(true);
         }
 
-        private void Act()
+        protected override void Act()
         {
-            _sessionMock.Raise(p => p.ChannelCloseReceived += null,
+            SessionMock.Raise(p => p.ChannelCloseReceived += null,
                 new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
         }
 
@@ -81,7 +85,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
         [TestMethod]
         public void TrySendMessageOnSessionShouldBeInvokedOnceForChannelCloseMessage()
         {
-            _sessionMock.Verify(
+            SessionMock.Verify(
                 p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)),
                 Times.Once);
         }
@@ -89,15 +93,15 @@ namespace Renci.SshNet.Tests.Classes.Channels
         [TestMethod]
         public void TrySendMessageOnSessionShouldNeverBeInvokedForChannelEofMessage()
         {
-            _sessionMock.Verify(
+            SessionMock.Verify(
                 p => p.TrySendMessage(It.Is<ChannelEofMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)),
                 Times.Never);
         }
 
         [TestMethod]
-        public void WaitOnHandleOnSessionShouldBeInvokedOnce()
+        public void TryWaitOnSessionShouldBeInvokedOnce()
         {
-            _sessionMock.Verify(p => p.WaitOnHandle(It.IsAny<EventWaitHandle>()), Times.Once);
+            SessionMock.Verify(p => p.TryWait(It.IsAny<EventWaitHandle>(), _channelCloseTimeout), Times.Once);
         }
 
         [TestMethod]

+ 43 - 41
src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_OnSessionChannelCloseReceived_SessionIsConnectedAndChannelIsOpen_EofReceived.cs

@@ -10,71 +10,73 @@ using Renci.SshNet.Tests.Common;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelTest_OnSessionChannelCloseReceived_SessionIsConnectedAndChannelIsOpen_EofReceived
+    public class ChannelTest_OnSessionChannelCloseReceived_SessionIsConnectedAndChannelIsOpen_EofReceived : ChannelTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localChannelNumber;
         private uint _localWindowSize;
         private uint _localPacketSize;
         private uint _remoteChannelNumber;
         private uint _remoteWindowSize;
         private uint _remotePacketSize;
+        private TimeSpan _channelCloseTimeout;
         private IList<ChannelEventArgs> _channelClosedRegister;
         private IList<ExceptionEventArgs> _channelExceptionRegister;
         private ManualResetEvent _channelClosedEventHandlerCompleted;
         private ChannelStub _channel;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _localWindowSize = (uint)random.Next(0, int.MaxValue);
-            _localPacketSize = (uint)random.Next(0, int.MaxValue);
-            _remoteChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _remoteWindowSize = (uint)random.Next(0, int.MaxValue);
-            _remotePacketSize = (uint)random.Next(0, int.MaxValue);
+
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _localWindowSize = (uint) random.Next(0, int.MaxValue);
+            _localPacketSize = (uint) random.Next(0, int.MaxValue);
+            _remoteChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _remoteWindowSize = (uint) random.Next(0, int.MaxValue);
+            _remotePacketSize = (uint) random.Next(0, int.MaxValue);
+            _channelCloseTimeout = TimeSpan.FromSeconds(random.Next(10, 20));
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
             _channelClosedEventHandlerCompleted = new ManualResetEvent(false);
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
-
+        protected override void SetupMocks()
+        {
             var sequence = new MockSequence();
 
-            _sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
-            _sessionMock.InSequence(sequence).Setup(
-                p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)))
-                .Returns(true);
-            _sessionMock.InSequence(sequence)
-                .Setup(s => s.WaitOnHandle(It.IsNotNull<EventWaitHandle>()))
-                .Callback<WaitHandle>(w => w.WaitOne());
+            SessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
+            SessionMock.InSequence(sequence).Setup(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber))).Returns(true);
+            SessionMock.InSequence(sequence).Setup(p => p.ConnectionInfo).Returns(ConnectionInfoMock.Object);
+            ConnectionInfoMock.InSequence(sequence).Setup(p => p.ChannelCloseTimeout).Returns(_channelCloseTimeout);
+            SessionMock.InSequence(sequence)
+                        .Setup(p => p.TryWait(It.IsAny<EventWaitHandle>(), _channelCloseTimeout))
+                        .Callback<WaitHandle, TimeSpan>((waitHandle, channelCloseTimeout) => waitHandle.WaitOne())
+                        .Returns(WaitResult.Success);
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
 
-            _channel = new ChannelStub(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelStub(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Closed += (sender, args) =>
-                {
-                    _channelClosedRegister.Add(args);
-                    Thread.Sleep(100);
-                    _channelClosedEventHandlerCompleted.Set();
-                };
+            {
+                _channelClosedRegister.Add(args);
+                Thread.Sleep(100);
+                _channelClosedEventHandlerCompleted.Set();
+            };
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.InitializeRemoteChannelInfo(_remoteChannelNumber, _remoteWindowSize, _remotePacketSize);
             _channel.SetIsOpen(true);
 
-            _sessionMock.Raise(p => p.ChannelEofReceived += null,
-                new MessageEventArgs<ChannelEofMessage>(new ChannelEofMessage(_localChannelNumber)));
+            SessionMock.Raise(p => p.ChannelEofReceived += null,
+                               new MessageEventArgs<ChannelEofMessage>(new ChannelEofMessage(_localChannelNumber)));
         }
 
-        private void Act()
+        protected override void Act()
         {
-            _sessionMock.Raise(p => p.ChannelCloseReceived += null,
-                new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
+            SessionMock.Raise(p => p.ChannelCloseReceived += null,
+                               new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
         }
 
         [TestMethod]
@@ -86,7 +88,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
         [TestMethod]
         public void TrySendMessageOnSessionShouldBeInvokedOnceForChannelCloseMessage()
         {
-            _sessionMock.Verify(
+            SessionMock.Verify(
                 p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)),
                 Times.Once);
         }
@@ -94,15 +96,15 @@ namespace Renci.SshNet.Tests.Classes.Channels
         [TestMethod]
         public void SendMessageOnSessionShouldNeverBeInvokedForChannelEofMessage()
         {
-            _sessionMock.Verify(
+            SessionMock.Verify(
                 p => p.TrySendMessage(It.Is<ChannelEofMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)),
                 Times.Never);
         }
 
         [TestMethod]
-        public void WaitOnHandleOnSessionShouldBeInvokedOnce()
+        public void TryWaitOnSessionShouldBeInvokedOnce()
         {
-            _sessionMock.Verify(p => p.WaitOnHandle(It.IsAny<EventWaitHandle>()), Times.Once);
+            SessionMock.Verify(p => p.TryWait(It.IsAny<EventWaitHandle>(), _channelCloseTimeout), Times.Once);
         }
 
         [TestMethod]
@@ -124,4 +126,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
             Assert.IsTrue(_channelClosedEventHandlerCompleted.WaitOne(0));
         }
     }
-}
+}

+ 18 - 18
src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_OnSessionChannelDataReceived_OnData_Exception.cs

@@ -8,9 +8,8 @@ using Renci.SshNet.Messages.Connection;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelTest_OnSessionChannelDataReceived_OnData_Exception
+    public class ChannelTest_OnSessionChannelDataReceived_OnData_Exception : ChannelTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localWindowSize;
         private uint _localPacketSize;
         private uint _localChannelNumber;
@@ -18,33 +17,34 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private IList<ExceptionEventArgs> _channelExceptionRegister;
         private Exception _onDataException;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localWindowSize = (uint)random.Next(1000, int.MaxValue);
+
+            _localWindowSize = (uint) random.Next(1000, int.MaxValue);
             _localPacketSize = _localWindowSize - 1;
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
             _onDataException = new SystemException();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
+        protected override void SetupMocks()
+        {
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
 
-            _channel = new ChannelStub(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelStub(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.OnDataException = _onDataException;
         }
 
-        private void Act()
+        protected override void Act()
         {
-            _sessionMock.Raise(s => s.ChannelDataReceived += null,
-                new MessageEventArgs<ChannelDataMessage>(new ChannelDataMessage(_localChannelNumber, new byte[0])));
+            SessionMock.Raise(s => s.ChannelDataReceived += null,
+                               new MessageEventArgs<ChannelDataMessage>(new ChannelDataMessage(_localChannelNumber, new byte[0])));
         }
 
         [TestMethod]
@@ -61,4 +61,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
             Assert.AreSame(_onDataException, _channel.OnErrorOccurredInvocations[0]);
         }
     }
-}
+}

+ 22 - 22
src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_OnSessionChannelEofReceived_OnEof_Exception.cs

@@ -8,9 +8,8 @@ using Renci.SshNet.Messages.Connection;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelTest_OnSessionChannelEofReceived_Exception
+    public class ChannelTest_OnSessionChannelEofReceived_Exception : ChannelTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localWindowSize;
         private uint _localPacketSize;
         private uint _localChannelNumber;
@@ -21,38 +20,39 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private IList<ExceptionEventArgs> _channelExceptionRegister;
         private Exception _onEofException;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localWindowSize = (uint)random.Next(0, 1000);
-            _localPacketSize = (uint)random.Next(1001, int.MaxValue);
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _remoteChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _remoteWindowSize = (uint)random.Next(0, int.MaxValue);
-            _remotePacketSize = (uint)random.Next(0, int.MaxValue);
+
+            _localWindowSize = (uint) random.Next(0, 1000);
+            _localPacketSize = (uint) random.Next(1001, int.MaxValue);
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _remoteChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _remoteWindowSize = (uint) random.Next(0, int.MaxValue);
+            _remotePacketSize = (uint) random.Next(0, int.MaxValue);
             _onEofException = new SystemException();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
+        protected override void SetupMocks()
+        {
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
 
-            _channel = new ChannelStub(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelStub(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.InitializeRemoteChannelInfo(_remoteChannelNumber, _remoteWindowSize, _remotePacketSize);
             _channel.SetIsOpen(true);
             _channel.OnEofException = _onEofException;
         }
 
-        private void Act()
+        protected override void Act()
         {
-            _sessionMock.Raise(s => s.ChannelEofReceived += null,
-                new MessageEventArgs<ChannelEofMessage>(new ChannelEofMessage(_localChannelNumber)));
+            SessionMock.Raise(s => s.ChannelEofReceived += null,
+                               new MessageEventArgs<ChannelEofMessage>(new ChannelEofMessage(_localChannelNumber)));
         }
 
         [TestMethod]
@@ -69,4 +69,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
             Assert.AreSame(_onEofException, _channel.OnErrorOccurredInvocations[0]);
         }
     }
-}
+}

+ 18 - 18
src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_OnSessionChannelExtendedDataReceived_OnExtendedData_Exception.cs

@@ -8,9 +8,8 @@ using Renci.SshNet.Messages.Connection;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelTest_OnSessionChannelExtendedDataReceived_OnExtendedData_Exception
+    public class ChannelTest_OnSessionChannelExtendedDataReceived_OnExtendedData_Exception : ChannelTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localWindowSize;
         private uint _localPacketSize;
         private uint _localChannelNumber;
@@ -18,33 +17,34 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private IList<ExceptionEventArgs> _channelExceptionRegister;
         private Exception _onExtendedDataException;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localWindowSize = (uint)random.Next(1000, int.MaxValue);
+
+            _localWindowSize = (uint) random.Next(1000, int.MaxValue);
             _localPacketSize = _localWindowSize - 1;
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
             _onExtendedDataException = new SystemException();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
+        protected override void SetupMocks()
+        {
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
 
-            _channel = new ChannelStub(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelStub(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.OnExtendedDataException = _onExtendedDataException;
         }
 
-        private void Act()
+        protected override void Act()
         {
-            _sessionMock.Raise(s => s.ChannelExtendedDataReceived += null,
-                new MessageEventArgs<ChannelExtendedDataMessage>(new ChannelExtendedDataMessage(_localChannelNumber, 5, new byte[0])));
+            SessionMock.Raise(s => s.ChannelExtendedDataReceived += null,
+                               new MessageEventArgs<ChannelExtendedDataMessage>(new ChannelExtendedDataMessage(_localChannelNumber, 5, new byte[0])));
         }
 
         [TestMethod]
@@ -61,4 +61,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
             Assert.AreSame(_onExtendedDataException, _channel.OnErrorOccurredInvocations[0]);
         }
     }
-}
+}

+ 19 - 19
src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_OnSessionChannelFailureReceived_OnFailure_Exception.cs

@@ -8,9 +8,8 @@ using Renci.SshNet.Messages.Connection;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelTest_OnSessionChannelFailureReceived_OnFailure_Exception
+    public class ChannelTest_OnSessionChannelFailureReceived_OnFailure_Exception : ChannelTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localWindowSize;
         private uint _localPacketSize;
         private uint _localChannelNumber;
@@ -18,33 +17,34 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private IList<ExceptionEventArgs> _channelExceptionRegister;
         private Exception _onFailureException;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localWindowSize = (uint)random.Next(0, 1000);
-            _localPacketSize = (uint)random.Next(1001, int.MaxValue);
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
+
+            _localWindowSize = (uint) random.Next(0, 1000);
+            _localPacketSize = (uint) random.Next(1001, int.MaxValue);
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
             _onFailureException = new SystemException();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
+        protected override void SetupMocks()
+        {
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
 
-            _channel = new ChannelStub(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelStub(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.OnFailureException = _onFailureException;
         }
 
-        private void Act()
+        protected override void Act()
         {
-            _sessionMock.Raise(s => s.ChannelFailureReceived += null,
-                new MessageEventArgs<ChannelFailureMessage>(new ChannelFailureMessage(_localChannelNumber)));
+            SessionMock.Raise(s => s.ChannelFailureReceived += null,
+                               new MessageEventArgs<ChannelFailureMessage>(new ChannelFailureMessage(_localChannelNumber)));
         }
 
         [TestMethod]
@@ -61,4 +61,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
             Assert.AreSame(_onFailureException, _channel.OnErrorOccurredInvocations[0]);
         }
     }
-}
+}

+ 20 - 20
src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_OnSessionChannelRequestReceived_OnRequest_Exception.cs

@@ -8,9 +8,8 @@ using Renci.SshNet.Messages.Connection;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelTest_OnSessionChannelRequestReceived_OnRequest_Exception
+    public class ChannelTest_OnSessionChannelRequestReceived_OnRequest_Exception : ChannelTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localWindowSize;
         private uint _localPacketSize;
         private uint _localChannelNumber;
@@ -19,36 +18,37 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private Exception _onRequestException;
         private SignalRequestInfo _requestInfo;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localWindowSize = (uint)random.Next(1000, int.MaxValue);
+
+            _localWindowSize = (uint) random.Next(1000, int.MaxValue);
             _localPacketSize = _localWindowSize - 1;
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
             _onRequestException = new SystemException();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
             _requestInfo = new SignalRequestInfo("ABC");
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
-            _sessionMock.Setup(p => p.ConnectionInfo)
-                .Returns(new ConnectionInfo("host", "user", new PasswordAuthenticationMethod("user", "password")));
+        protected override void SetupMocks()
+        {
+            SessionMock.Setup(p => p.ConnectionInfo)
+                        .Returns(new ConnectionInfo("host", "user", new PasswordAuthenticationMethod("user", "password")));
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
 
-            _channel = new ChannelStub(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelStub(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.OnRequestException = _onRequestException;
         }
 
-        private void Act()
+        protected override void Act()
         {
-            _sessionMock.Raise(s => s.ChannelRequestReceived += null,
-                new MessageEventArgs<ChannelRequestMessage>(new ChannelRequestMessage(_localChannelNumber, _requestInfo)));
+            SessionMock.Raise(s => s.ChannelRequestReceived += null,
+                               new MessageEventArgs<ChannelRequestMessage>(new ChannelRequestMessage(_localChannelNumber, _requestInfo)));
         }
 
         [TestMethod]
@@ -65,4 +65,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
             Assert.AreSame(_onRequestException, _channel.OnErrorOccurredInvocations[0]);
         }
     }
-}
+}

+ 19 - 19
src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_OnSessionChannelSuccessReceived_OnSuccess_Exception.cs

@@ -8,9 +8,8 @@ using Renci.SshNet.Messages.Connection;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelTest_OnSessionChannelSuccessReceived_OnSuccess_Exception
+    public class ChannelTest_OnSessionChannelSuccessReceived_OnSuccess_Exception : ChannelTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localWindowSize;
         private uint _localPacketSize;
         private uint _localChannelNumber;
@@ -18,33 +17,34 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private IList<ExceptionEventArgs> _channelExceptionRegister;
         private Exception _onSuccessException;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _localWindowSize = (uint)random.Next(0, 1000);
-            _localPacketSize = (uint)random.Next(1001, int.MaxValue);
+
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _localWindowSize = (uint) random.Next(0, 1000);
+            _localPacketSize = (uint) random.Next(1001, int.MaxValue);
             _onSuccessException = new SystemException();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
+        protected override void SetupMocks()
+        {
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
 
-            _channel = new ChannelStub(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelStub(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.OnSuccessException = _onSuccessException;
         }
 
-        private void Act()
+        protected override void Act()
         {
-            _sessionMock.Raise(s => s.ChannelSuccessReceived += null,
-                new MessageEventArgs<ChannelSuccessMessage>(new ChannelSuccessMessage(_localChannelNumber)));
+            SessionMock.Raise(s => s.ChannelSuccessReceived += null,
+                               new MessageEventArgs<ChannelSuccessMessage>(new ChannelSuccessMessage(_localChannelNumber)));
         }
 
         [TestMethod]
@@ -61,4 +61,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
             Assert.AreSame(_onSuccessException, _channel.OnErrorOccurredInvocations[0]);
         }
     }
-}
+}

+ 21 - 21
src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_OnSessionChannelWindowAdjustReceived_OnWindowAdjust_Exception.cs

@@ -8,9 +8,8 @@ using Renci.SshNet.Messages.Connection;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelTest_OnSessionChannelWindowAdjustReceived_OnWindowAdjust_Exception
+    public class ChannelTest_OnSessionChannelWindowAdjustReceived_OnWindowAdjust_Exception : ChannelTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localChannelNumber;
         private uint _localWindowSize;
         private uint _localPacketSize;
@@ -22,38 +21,39 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private Exception _onWindowAdjustException;
         private uint _bytesToAdd;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _localWindowSize = (uint)random.Next(1000, int.MaxValue);
+
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _localWindowSize = (uint) random.Next(1000, int.MaxValue);
             _localPacketSize = _localWindowSize - 1;
-            _remoteChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _remoteWindowSize = (uint)random.Next(1000, int.MaxValue);
+            _remoteChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _remoteWindowSize = (uint) random.Next(1000, int.MaxValue);
             _remotePacketSize = _localWindowSize - 1;
-            _bytesToAdd = (uint)random.Next(0, int.MaxValue);
+            _bytesToAdd = (uint) random.Next(0, int.MaxValue);
             _onWindowAdjustException = new SystemException();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
+        protected override void SetupMocks()
+        {
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
 
-            _channel = new ChannelStub(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelStub(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.InitializeRemoteChannelInfo(_remoteChannelNumber, _remoteWindowSize, _remotePacketSize);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.OnWindowAdjustException = _onWindowAdjustException;
         }
 
-        private void Act()
+        protected override void Act()
         {
-            _sessionMock.Raise(s => s.ChannelWindowAdjustReceived += null,
-                new MessageEventArgs<ChannelWindowAdjustMessage>(new ChannelWindowAdjustMessage(_localChannelNumber, _bytesToAdd)));
+            SessionMock.Raise(s => s.ChannelWindowAdjustReceived += null,
+                               new MessageEventArgs<ChannelWindowAdjustMessage>(new ChannelWindowAdjustMessage(_localChannelNumber, _bytesToAdd)));
         }
 
         [TestMethod]
@@ -70,4 +70,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
             Assert.AreSame(_onWindowAdjustException, _channel.OnErrorOccurredInvocations[0]);
         }
     }
-}
+}

+ 17 - 17
src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_OnSessionDisconnected_OnDisconnected_Exception.cs

@@ -7,9 +7,8 @@ using Renci.SshNet.Common;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelTest_OnSessionDisconnected_OnDisconnected_Exception
+    public class ChannelTest_OnSessionDisconnected_OnDisconnected_Exception : ChannelTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localWindowSize;
         private uint _localPacketSize;
         private uint _localChannelNumber;
@@ -17,32 +16,33 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private IList<ExceptionEventArgs> _channelExceptionRegister;
         private Exception _onDisconnectedException;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localWindowSize = (uint)random.Next(1000, int.MaxValue);
+
+            _localWindowSize = (uint) random.Next(1000, int.MaxValue);
             _localPacketSize = _localWindowSize - 1;
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
             _onDisconnectedException = new SystemException();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
+        protected override void SetupMocks()
+        {
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
 
-            _channel = new ChannelStub(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelStub(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.OnDisconnectedException = _onDisconnectedException;
         }
 
-        private void Act()
+        protected override void Act()
         {
-            _sessionMock.Raise(s => s.Disconnected += null, EventArgs.Empty);
+            SessionMock.Raise(s => s.Disconnected += null, EventArgs.Empty);
         }
 
         [TestMethod]
@@ -59,4 +59,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
             Assert.AreSame(_onDisconnectedException, _channel.OnErrorOccurredInvocations[0]);
         }
     }
-}
+}

+ 21 - 22
src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_OnSessionDisconnected_SessionIsConnectedAndChannelIsOpen.cs

@@ -7,9 +7,8 @@ using Renci.SshNet.Common;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelTest_OnSessionDisconnected_SessionIsConnectedAndChannelIsOpen
+    public class ChannelTest_OnSessionDisconnected_SessionIsConnectedAndChannelIsOpen : ChannelTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localChannelNumber;
         private uint _localWindowSize;
         private uint _localPacketSize;
@@ -20,39 +19,39 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private List<ChannelEventArgs> _channelClosedRegister;
         private IList<ExceptionEventArgs> _channelExceptionRegister;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _localWindowSize = (uint)random.Next(0, int.MaxValue);
-            _localPacketSize = (uint)random.Next(0, int.MaxValue);
-            _remoteChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _remoteWindowSize = (uint)random.Next(0, int.MaxValue);
-            _remotePacketSize = (uint)random.Next(0, int.MaxValue);
+
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _localWindowSize = (uint) random.Next(0, int.MaxValue);
+            _localPacketSize = (uint) random.Next(0, int.MaxValue);
+            _remoteChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _remoteWindowSize = (uint) random.Next(0, int.MaxValue);
+            _remotePacketSize = (uint) random.Next(0, int.MaxValue);
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
+        protected override void SetupMocks()
+        {
+            SessionMock.Setup(p => p.IsConnected).Returns(true);
+        }
 
-            _sessionMock.Setup(p => p.IsConnected).Returns(true);
+        protected override void Arrange()
+        {
+            base.Arrange();
 
-            _channel = new ChannelStub(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelStub(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Closed += (sender, args) => _channelClosedRegister.Add(args);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.InitializeRemoteChannelInfo(_remoteChannelNumber, _remoteWindowSize, _remotePacketSize);
             _channel.SetIsOpen(true);
         }
 
-        private void Act()
+        protected override void Act()
         {
-            _sessionMock.Raise(s => s.Disconnected += null, EventArgs.Empty);
+            SessionMock.Raise(s => s.Disconnected += null, EventArgs.Empty);
         }
 
         [TestMethod]
@@ -73,4 +72,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
             Assert.AreEqual(0, _channelExceptionRegister.Count);
         }
     }
-}
+}

+ 17 - 18
src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_OnSessionErrorOccurred_OnErrorOccurred_Exception.cs

@@ -1,15 +1,13 @@
 using System;
 using System.Collections.Generic;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Moq;
 using Renci.SshNet.Common;
 
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelTest_OnSessionErrorOccurred_OnErrorOccurred_Exception
+    public class ChannelTest_OnSessionErrorOccurred_OnErrorOccurred_Exception : ChannelTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localWindowSize;
         private uint _localPacketSize;
         private uint _localChannelNumber;
@@ -18,33 +16,34 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private Exception _onErrorOccurredException;
         private Exception _errorOccurredException;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localWindowSize = (uint)random.Next(1000, int.MaxValue);
+
+            _localWindowSize = (uint) random.Next(1000, int.MaxValue);
             _localPacketSize = _localWindowSize - 1;
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
             _onErrorOccurredException = new SystemException();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
             _errorOccurredException = new SystemException();
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
+        protected override void SetupMocks()
+        {
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
 
-            _channel = new ChannelStub(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelStub(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.OnErrorOccurredException = _onErrorOccurredException;
         }
 
-        private void Act()
+        protected override void Act()
         {
-            _sessionMock.Raise(s => s.ErrorOccured += null, new ExceptionEventArgs(_errorOccurredException));
+            SessionMock.Raise(s => s.ErrorOccured += null, new ExceptionEventArgs(_errorOccurredException));
         }
 
         [TestMethod]
@@ -61,4 +60,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
             Assert.AreSame(_errorOccurredException, _channel.OnErrorOccurredInvocations[0]);
         }
     }
-}
+}

+ 18 - 18
src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_SendEof_ChannelIsNotOpen.cs

@@ -8,9 +8,8 @@ using Renci.SshNet.Messages;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelTest_SendEof_ChannelIsNotOpen
+    public class ChannelTest_SendEof_ChannelIsNotOpen : ChannelTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localWindowSize;
         private uint _localPacketSize;
         private uint _localChannelNumber;
@@ -19,31 +18,32 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private IList<ExceptionEventArgs> _channelExceptionRegister;
         private InvalidOperationException _actualException;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _localWindowSize = (uint)random.Next(0, int.MaxValue);
-            _localPacketSize = (uint)random.Next(0, int.MaxValue);
+
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _localWindowSize = (uint) random.Next(0, int.MaxValue);
+            _localPacketSize = (uint) random.Next(0, int.MaxValue);
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
             _actualException = null;
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
+        protected override void SetupMocks()
+        {
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
 
-            _channel = new ChannelStub(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelStub(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Closed += (sender, args) => _channelClosedRegister.Add(args);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
         }
 
-        private void Act()
+        protected override void Act()
         {
             try
             {
@@ -73,7 +73,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
         [TestMethod]
         public void SendMessageOnSessionShouldNeverBeInvoked()
         {
-            _sessionMock.Verify(p => p.SendMessage(It.IsAny<Message>()), Times.Never);
+            SessionMock.Verify(p => p.SendMessage(It.IsAny<Message>()), Times.Never);
         }
 
         [TestMethod]
@@ -88,4 +88,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
             Assert.AreEqual(0, _channelExceptionRegister.Count);
         }
     }
-}
+}

+ 21 - 22
src/Renci.SshNet.Tests/Classes/Channels/ChannelTest_SendEof_ChannelIsOpen.cs

@@ -8,9 +8,8 @@ using Renci.SshNet.Messages.Connection;
 namespace Renci.SshNet.Tests.Classes.Channels
 {
     [TestClass]
-    public class ChannelTest_SendEof_ChannelIsOpen
+    public class ChannelTest_SendEof_ChannelIsOpen : ChannelTestBase
     {
-        private Mock<ISession> _sessionMock;
         private uint _localChannelNumber;
         private uint _localWindowSize;
         private uint _localPacketSize;
@@ -21,37 +20,37 @@ namespace Renci.SshNet.Tests.Classes.Channels
         private List<ChannelEventArgs> _channelClosedRegister;
         private IList<ExceptionEventArgs> _channelExceptionRegister;
 
-        [TestInitialize]
-        public void Initialize()
-        {
-            Arrange();
-            Act();
-        }
-
-        private void Arrange()
+        protected override void SetupData()
         {
             var random = new Random();
-            _localChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _localWindowSize = (uint)random.Next(0, int.MaxValue);
-            _localPacketSize = (uint)random.Next(0, int.MaxValue);
-            _remoteChannelNumber = (uint)random.Next(0, int.MaxValue);
-            _remoteWindowSize = (uint)random.Next(0, int.MaxValue);
-            _remotePacketSize = (uint)random.Next(0, int.MaxValue);
+
+            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _localWindowSize = (uint) random.Next(0, int.MaxValue);
+            _localPacketSize = (uint) random.Next(0, int.MaxValue);
+            _remoteChannelNumber = (uint) random.Next(0, int.MaxValue);
+            _remoteWindowSize = (uint) random.Next(0, int.MaxValue);
+            _remotePacketSize = (uint) random.Next(0, int.MaxValue);
             _channelClosedRegister = new List<ChannelEventArgs>();
             _channelExceptionRegister = new List<ExceptionEventArgs>();
+        }
 
-            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
+        protected override void SetupMocks()
+        {
+            SessionMock.Setup(p => p.SendMessage(It.Is<ChannelEofMessage>(e => e.LocalChannelNumber == _remoteChannelNumber)));
+        }
 
-            _sessionMock.Setup(p => p.SendMessage(It.Is<ChannelEofMessage>(e => e.LocalChannelNumber == _remoteChannelNumber)));
+        protected override void Arrange()
+        {
+            base.Arrange();
 
-            _channel = new ChannelStub(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
+            _channel = new ChannelStub(SessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
             _channel.Closed += (sender, args) => _channelClosedRegister.Add(args);
             _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
             _channel.InitializeRemoteChannelInfo(_remoteChannelNumber, _remoteWindowSize, _remotePacketSize);
             _channel.SetIsOpen(true);
         }
 
-        private void Act()
+        protected override void Act()
         {
             _channel.SendEof();
         }
@@ -65,7 +64,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
         [TestMethod]
         public void SendMessageOnSessionShouldBeInvokedOnceWithChannelEofMessage()
         {
-            _sessionMock.Verify(
+            SessionMock.Verify(
                 p => p.SendMessage(It.Is<ChannelEofMessage>(e => e.LocalChannelNumber == _remoteChannelNumber)),
                 Times.Once);
         }
@@ -82,4 +81,4 @@ namespace Renci.SshNet.Tests.Classes.Channels
             Assert.AreEqual(0, _channelExceptionRegister.Count);
         }
     }
-}
+}

+ 90 - 4
src/Renci.SshNet.Tests/Classes/SessionTest_Connected.cs

@@ -71,7 +71,7 @@ namespace Renci.SshNet.Tests.Classes
         [TestMethod]
         public void WaitOnHandle_WaitHandle_ShouldThrowArgumentNullExceptionWhenWaitHandleIsNull()
         {
-            WaitHandle waitHandle = null;
+            const WaitHandle waitHandle = null;
 
             try
             {
@@ -88,7 +88,7 @@ namespace Renci.SshNet.Tests.Classes
         [TestMethod]
         public void WaitOnHandle_WaitHandleAndTimeout_ShouldThrowArgumentNullExceptionWhenWaitHandleIsNull()
         {
-            WaitHandle waitHandle = null;
+            const WaitHandle waitHandle = null;
             var timeout = TimeSpan.FromMinutes(5);
 
             try
@@ -151,7 +151,7 @@ namespace Renci.SshNet.Tests.Classes
         [TestMethod]
         public void ISession_WaitOnHandleShouldThrowArgumentNullExceptionWhenWaitHandleIsNull()
         {
-            WaitHandle waitHandle = null;
+            const WaitHandle waitHandle = null;
             var session = (ISession) Session;
 
             try
@@ -165,5 +165,91 @@ namespace Renci.SshNet.Tests.Classes
                 Assert.AreEqual("waitHandle", ex.ParamName);
             }
         }
+
+        [TestMethod]
+        public void ISession_TryWait_WaitHandleAndTimeout_ShouldReturnSuccessIfWaitHandleIsSignaled()
+        {
+            var session = (ISession) Session;
+            var waitHandle = new ManualResetEvent(true);
+
+            var result = session.TryWait(waitHandle, TimeSpan.FromMilliseconds(0));
+
+            Assert.AreEqual(WaitResult.Success, result);
+        }
+
+        [TestMethod]
+        public void ISession_TryWait_WaitHandleAndTimeout_ShouldReturnTimedOutIfWaitHandleIsNotSignaled()
+        {
+            var session = (ISession) Session;
+            var waitHandle = new ManualResetEvent(false);
+
+            var result = session.TryWait(waitHandle, TimeSpan.FromMilliseconds(0));
+
+            Assert.AreEqual(WaitResult.TimedOut, result);
+        }
+
+        [TestMethod]
+        public void ISession_TryWait_WaitHandleAndTimeout_ShouldThrowArgumentNullExceptionWhenWaitHandleIsNull()
+        {
+            var session = (ISession) Session;
+            const WaitHandle waitHandle = null;
+
+            try
+            {
+                session.TryWait(waitHandle, Session.InfiniteTimeSpan);
+                Assert.Fail();
+            }
+            catch (ArgumentNullException ex)
+            {
+                Assert.IsNull(ex.InnerException);
+                Assert.AreEqual("waitHandle", ex.ParamName);
+            }
+        }
+
+        [TestMethod]
+        public void ISession_TryWait_WaitHandleAndTimeoutAndException_ShouldReturnSuccessIfWaitHandleIsSignaled()
+        {
+            var session = (ISession) Session;
+            var waitHandle = new ManualResetEvent(true);
+            Exception exception;
+
+            var result = session.TryWait(waitHandle, TimeSpan.FromMilliseconds(0), out exception);
+
+            Assert.AreEqual(WaitResult.Success, result);
+            Assert.IsNull(exception);
+        }
+
+        [TestMethod]
+        public void ISession_TryWait_WaitHandleAndTimeoutAndException_ShouldReturnTimedOutIfWaitHandleIsNotSignaled()
+        {
+            var session = (ISession) Session;
+            var waitHandle = new ManualResetEvent(false);
+            Exception exception;
+
+            var result = session.TryWait(waitHandle, TimeSpan.FromMilliseconds(0), out exception);
+
+            Assert.AreEqual(WaitResult.TimedOut, result);
+            Assert.IsNull(exception);
+        }
+
+        [TestMethod]
+        public void ISession_TryWait_WaitHandleAndTimeoutAndException_ShouldThrowArgumentNullExceptionWhenWaitHandleIsNull()
+        {
+            var session = (ISession) Session;
+            const WaitHandle waitHandle = null;
+            Exception exception = null;
+
+            try
+            {
+                session.TryWait(waitHandle, Session.InfiniteTimeSpan, out exception);
+                Assert.Fail();
+            }
+            catch (ArgumentNullException ex)
+            {
+                Assert.IsNull(ex.InnerException);
+                Assert.AreEqual("waitHandle", ex.ParamName);
+                Assert.IsNull(exception);
+            }
+        }
     }
-}
+}

+ 58 - 7
src/Renci.SshNet.Tests/Classes/SessionTest_Connected_ConnectionReset.cs

@@ -1,4 +1,5 @@
-using System.Diagnostics;
+using System;
+using System.Diagnostics;
 using System.Net.Sockets;
 using System.Threading;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
@@ -69,9 +70,8 @@ namespace Renci.SshNet.Tests.Classes
             Assert.AreEqual(typeof(SocketException), innerException.GetType());
 
             var socketException = (SocketException) innerException;
+            Assert.AreSame(connectionException.Message, socketException.Message);
             Assert.AreEqual(SocketError.ConnectionReset, socketException.SocketErrorCode);
-
-            Assert.AreSame(innerException.Message, connectionException.Message);
         }
 
         [TestMethod]
@@ -140,7 +140,7 @@ namespace Renci.SshNet.Tests.Classes
         }
 
         [TestMethod]
-        public void ISession_WaitOnHandleShouldThrowSshConnectionExceptionDetailingConnectionReset()
+        public void ISession_WaitOnHandle_WaitHandle_ShouldThrowSshConnectionExceptionDetailingConnectionReset()
         {
             var session = (ISession) Session;
             var waitHandle = new ManualResetEvent(false);
@@ -158,12 +158,63 @@ namespace Renci.SshNet.Tests.Classes
                 Assert.IsNotNull(innerException);
                 Assert.AreEqual(typeof(SocketException), innerException.GetType());
 
-                var socketException = (SocketException)ex.InnerException;
+                var socketException = (SocketException) ex.InnerException;
+                Assert.IsNotNull(socketException);
+                Assert.IsNull(socketException.InnerException);
+                Assert.AreSame(innerException.Message, ex.Message);
                 Assert.AreEqual(SocketError.ConnectionReset, socketException.SocketErrorCode);
+            }
+        }
 
-                Assert.AreSame(innerException.Message, ex.Message);
+        [TestMethod]
+        public void ISession_WaitOnHandle_WaitHandleAndTimeout_ShouldThrowSshConnectionExceptionDetailingConnectionReset()
+        {
+            var session = (ISession) Session;
+            var waitHandle = new ManualResetEvent(false);
+
+            try
+            {
+                session.WaitOnHandle(waitHandle, Session.InfiniteTimeSpan);
+                Assert.Fail();
+            }
+            catch (SshConnectionException ex)
+            {
+                Assert.AreEqual(DisconnectReason.ConnectionLost, ex.DisconnectReason);
+
+                var innerException = ex.InnerException;
+                Assert.IsNotNull(innerException);
+                Assert.AreEqual(typeof(SocketException), innerException.GetType());
 
+                var socketException = (SocketException) ex.InnerException;
+                Assert.IsNotNull(socketException);
+                Assert.IsNull(socketException.InnerException);
+                Assert.AreSame(innerException.Message, socketException.Message);
+                Assert.AreEqual(SocketError.ConnectionReset, socketException.SocketErrorCode);
             }
         }
+
+        [TestMethod]
+        public void ISession_TryWait_WaitHandleAndTimeout_ShouldReturnDisconnected()
+        {
+            var session = (ISession) Session;
+            var waitHandle = new ManualResetEvent(false);
+
+            var result = session.TryWait(waitHandle, Session.InfiniteTimeSpan);
+
+            Assert.AreEqual(WaitResult.Disconnected, result);
+        }
+
+        [TestMethod]
+        public void ISession_TryWait_WaitHandleAndTimeoutAndException_ShouldReturnDisconnected()
+        {
+            var session = (ISession) Session;
+            var waitHandle = new ManualResetEvent(false);
+            Exception exception;
+
+            var result = session.TryWait(waitHandle, Session.InfiniteTimeSpan, out exception);
+
+            Assert.AreEqual(WaitResult.Disconnected, result);
+            Assert.IsNull(exception);
+        }
     }
-}
+}

+ 48 - 4
src/Renci.SshNet.Tests/Classes/SessionTest_Connected_Disconnect.cs

@@ -1,4 +1,5 @@
-using System.Diagnostics;
+using System;
+using System.Diagnostics;
 using System.Net.Sockets;
 using System.Threading;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
@@ -92,7 +93,7 @@ namespace Renci.SshNet.Tests.Classes
         [TestMethod]
         public void ISession_MessageListenerCompletedShouldBeSignaled()
         {
-            var session = (ISession)Session;
+            var session = (ISession) Session;
 
             Assert.IsNotNull(session.MessageListenerCompleted);
             Assert.IsTrue(session.MessageListenerCompleted.WaitOne());
@@ -127,7 +128,7 @@ namespace Renci.SshNet.Tests.Classes
         }
 
         [TestMethod]
-        public void ISession_WaitOnHandleShouldThrowSshConnectionExceptionDetailingBadPacket()
+        public void ISession_WaitOnHandle_WaitHandle_ShouldThrowSshConnectionExceptionDetailingBadPacket()
         {
             var session = (ISession) Session;
             var waitHandle = new ManualResetEvent(false);
@@ -144,5 +145,48 @@ namespace Renci.SshNet.Tests.Classes
                 Assert.AreEqual("Client not connected.", ex.Message);
             }
         }
+
+        [TestMethod]
+        public void ISession_WaitOnHandle_WaitHandleAndTimeout_ShouldThrowSshConnectionExceptionDetailingBadPacket()
+        {
+            var session = (ISession) Session;
+            var waitHandle = new ManualResetEvent(false);
+
+            try
+            {
+                session.WaitOnHandle(waitHandle, Session.InfiniteTimeSpan);
+                Assert.Fail();
+            }
+            catch (SshConnectionException ex)
+            {
+                Assert.AreEqual(DisconnectReason.None, ex.DisconnectReason);
+                Assert.IsNull(ex.InnerException);
+                Assert.AreEqual("Client not connected.", ex.Message);
+            }
+        }
+
+        [TestMethod]
+        public void ISession_TryWait_WaitHandleAndTimeout_ShouldReturnDisconnected()
+        {
+            var session = (ISession) Session;
+            var waitHandle = new ManualResetEvent(false);
+
+            var result = session.TryWait(waitHandle, Session.InfiniteTimeSpan);
+
+            Assert.AreEqual(WaitResult.Disconnected, result);
+        }
+
+        [TestMethod]
+        public void ISession_TryWait_WaitHandleAndTimeoutAndException_ShouldReturnDisconnected()
+        {
+            var session = (ISession) Session;
+            var waitHandle = new ManualResetEvent(false);
+            Exception exception;
+
+            var result = session.TryWait(waitHandle, Session.InfiniteTimeSpan, out exception);
+
+            Assert.AreEqual(WaitResult.Disconnected, result);
+            Assert.IsNull(exception);
+        }
     }
-}
+}

+ 60 - 8
src/Renci.SshNet.Tests/Classes/SessionTest_Connected_ServerSendsBadPacket.cs

@@ -1,4 +1,5 @@
-using System.Diagnostics;
+using System;
+using System.Diagnostics;
 using System.Net.Sockets;
 using System.Threading;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
@@ -11,12 +12,20 @@ namespace Renci.SshNet.Tests.Classes
     [TestClass]
     public class SessionTest_Connected_ServerSendsBadPacket : SessionTest_ConnectedBase
     {
+        private byte[] _packet;
+
+        protected override void SetupData()
+        {
+            base.SetupData();
+
+            _packet = new byte[] {0x0a, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05};
+        }
+
         protected override void Act()
         {
-            var badPacket = new byte[] { 0x0a, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05 };
-            ServerSocket.Send(badPacket, 0, badPacket.Length, SocketFlags.None);
+            ServerSocket.Send(_packet, 0, _packet.Length, SocketFlags.None);
 
-            // give session some time to react to bad packet
+            // give session some time to process packet
             Thread.Sleep(200);
         }
 
@@ -60,7 +69,7 @@ namespace Renci.SshNet.Tests.Classes
 
             var exception = errorOccurred.Exception;
             Assert.IsNotNull(exception);
-            Assert.AreEqual(typeof (SshConnectionException), exception.GetType());
+            Assert.AreEqual(typeof(SshConnectionException), exception.GetType());
 
             var connectionException = (SshConnectionException) exception;
             Assert.AreEqual(DisconnectReason.ProtocolError, connectionException.DisconnectReason);
@@ -109,7 +118,7 @@ namespace Renci.SshNet.Tests.Classes
         [TestMethod]
         public void ISession_MessageListenerCompletedShouldBeSignaled()
         {
-            var session = (ISession)Session;
+            var session = (ISession) Session;
 
             Assert.IsNotNull(session.MessageListenerCompleted);
             Assert.IsTrue(session.MessageListenerCompleted.WaitOne());
@@ -144,7 +153,7 @@ namespace Renci.SshNet.Tests.Classes
         }
 
         [TestMethod]
-        public void ISession_WaitOnHandleShouldThrowSshConnectionExceptionDetailingBadPacket()
+        public void ISession_WaitOnHandle_WaitHandle_ShouldThrowSshConnectionExceptionDetailingBadPacket()
         {
             var session = (ISession) Session;
             var waitHandle = new ManualResetEvent(false);
@@ -161,5 +170,48 @@ namespace Renci.SshNet.Tests.Classes
                 Assert.AreEqual("Bad packet length: 168101125.", ex.Message);
             }
         }
+
+        [TestMethod]
+        public void ISession_WaitOnHandleAndTimeout_WaitHandle_ShouldThrowSshConnectionExceptionDetailingBadPacket()
+        {
+            var session = (ISession) Session;
+            var waitHandle = new ManualResetEvent(false);
+
+            try
+            {
+                session.WaitOnHandle(waitHandle, Session.InfiniteTimeSpan);
+                Assert.Fail();
+            }
+            catch (SshConnectionException ex)
+            {
+                Assert.AreEqual(DisconnectReason.ProtocolError, ex.DisconnectReason);
+                Assert.IsNull(ex.InnerException);
+                Assert.AreEqual("Bad packet length: 168101125.", ex.Message);
+            }
+        }
+
+        [TestMethod]
+        public void ISession_TryWait_WaitHandleAndTimeout_ShouldReturnDisconnected()
+        {
+            var session = (ISession) Session;
+            var waitHandle = new ManualResetEvent(false);
+
+            var result = session.TryWait(waitHandle, Session.InfiniteTimeSpan);
+
+            Assert.AreEqual(WaitResult.Disconnected, result);
+        }
+
+        [TestMethod]
+        public void ISession_TryWait_WaitHandleAndTimeoutAndException_ShouldReturnDisconnected()
+        {
+            var session = (ISession) Session;
+            var waitHandle = new ManualResetEvent(false);
+            Exception exception;
+
+            var result = session.TryWait(waitHandle, Session.InfiniteTimeSpan, out exception);
+
+            Assert.AreEqual(WaitResult.Disconnected, result);
+            Assert.IsNull(exception);
+        }
     }
-}
+}

+ 64 - 9
src/Renci.SshNet.Tests/Classes/SessionTest_Connected_ServerSendsDisconnectMessage.cs

@@ -1,4 +1,5 @@
-using System.Diagnostics;
+using System;
+using System.Diagnostics;
 using System.Globalization;
 using System.Net.Sockets;
 using System.Threading;
@@ -8,8 +9,10 @@ using Renci.SshNet.Messages.Transport;
 
 namespace Renci.SshNet.Tests.Classes
 {
+    [TestClass]
     public class SessionTest_Connected_ServerSendsDisconnectMessage : SessionTest_ConnectedBase
     {
+        private byte[] _packet;
         private DisconnectMessage _disconnectMessage;
 
         protected override void SetupData()
@@ -17,14 +20,15 @@ namespace Renci.SshNet.Tests.Classes
             base.SetupData();
 
             _disconnectMessage = new DisconnectMessage(DisconnectReason.ServiceNotAvailable, "Not today!");
+            _packet = _disconnectMessage.GetPacket(8, null);
         }
 
         protected override void Act()
         {
-            var disconnect = _disconnectMessage.GetPacket(8, null);
-            ServerSocket.Send(disconnect, 4, disconnect.Length - 4, SocketFlags.None);
+            ServerSocket.Send(_packet, 4, _packet.Length - 4, SocketFlags.None);
 
-            Session.Disconnect();
+            // give session some time to process packet
+            Thread.Sleep(200);
         }
 
         [TestMethod]
@@ -110,7 +114,7 @@ namespace Renci.SshNet.Tests.Classes
         [TestMethod]
         public void ISession_MessageListenerCompletedShouldBeSignaled()
         {
-            var session = (ISession)Session;
+            var session = (ISession) Session;
 
             Assert.IsNotNull(session.MessageListenerCompleted);
             Assert.IsTrue(session.MessageListenerCompleted.WaitOne());
@@ -145,9 +149,9 @@ namespace Renci.SshNet.Tests.Classes
         }
 
         [TestMethod]
-        public void ISession_WaitOnHandleShouldThrowSshConnectionExceptionDetailingDisconnectReason()
+        public void ISession_WaitOnHandle_WaitHandle_ShouldThrowSshConnectionExceptionDetailingDisconnectReason()
         {
-            var session = (ISession)Session;
+            var session = (ISession) Session;
             var waitHandle = new ManualResetEvent(false);
 
             try
@@ -159,8 +163,59 @@ namespace Renci.SshNet.Tests.Classes
             {
                 Assert.AreEqual(DisconnectReason.ServiceNotAvailable, ex.DisconnectReason);
                 Assert.IsNull(ex.InnerException);
-                Assert.AreEqual(string.Format(CultureInfo.InvariantCulture, "The connection was closed by the server: {0} ({1}).", _disconnectMessage.Description, _disconnectMessage.ReasonCode), ex.Message);
+                Assert.AreEqual(string.Format(CultureInfo.InvariantCulture,
+                                              "The connection was closed by the server: {0} ({1}).",
+                                              _disconnectMessage.Description,
+                                              _disconnectMessage.ReasonCode),
+                                ex.Message);
+            }
+        }
+
+        [TestMethod]
+        public void ISession_WaitOnHandle_WaitHandleAndTimeout_ShouldThrowSshConnectionExceptionDetailingDisconnectReason()
+        {
+            var session = (ISession) Session;
+            var waitHandle = new ManualResetEvent(false);
+
+            try
+            {
+                session.WaitOnHandle(waitHandle, Session.InfiniteTimeSpan);
+                Assert.Fail();
             }
+            catch (SshConnectionException ex)
+            {
+                Assert.AreEqual(DisconnectReason.ServiceNotAvailable, ex.DisconnectReason);
+                Assert.IsNull(ex.InnerException);
+                Assert.AreEqual(string.Format(CultureInfo.InvariantCulture,
+                                              "The connection was closed by the server: {0} ({1}).",
+                                              _disconnectMessage.Description,
+                                              _disconnectMessage.ReasonCode),
+                                ex.Message);
+            }
+        }
+
+        [TestMethod]
+        public void ISession_TryWait_WaitHandleAndTimeout_ShouldReturnDisconnected()
+        {
+            var session = (ISession) Session;
+            var waitHandle = new ManualResetEvent(false);
+
+            var result = session.TryWait(waitHandle, Session.InfiniteTimeSpan);
+
+            Assert.AreEqual(WaitResult.Disconnected, result);
+        }
+
+        [TestMethod]
+        public void ISession_TryWait_WaitHandleAndTimeoutAndException_ShouldReturnDisconnected()
+        {
+            var session = (ISession) Session;
+            var waitHandle = new ManualResetEvent(false);
+            Exception exception;
+
+            var result = session.TryWait(waitHandle, Session.InfiniteTimeSpan, out exception);
+
+            Assert.AreEqual(WaitResult.Disconnected, result);
+            Assert.IsNull(exception);
         }
     }
-}
+}

+ 35 - 6
src/Renci.SshNet.Tests/Classes/SessionTest_Connected_ServerSendsDisconnectMessageAndShutsDownSocket.cs

@@ -1,4 +1,5 @@
-using System.Diagnostics;
+using System;
+using System.Diagnostics;
 using System.Globalization;
 using System.Net.Sockets;
 using System.Threading;
@@ -143,7 +144,7 @@ namespace Renci.SshNet.Tests.Classes
         [TestMethod]
         public void ISession_TrySendMessageShouldReturnFalse()
         {
-            var session = (ISession)Session;
+            var session = (ISession) Session;
 
             var actual = session.TrySendMessage(new IgnoreMessage());
 
@@ -151,9 +152,9 @@ namespace Renci.SshNet.Tests.Classes
         }
 
         [TestMethod]
-        public void ISession_WaitOnHandleShouldThrowSshConnectionExceptionDetailingDisconnectReason()
+        public void ISession_WaitOnHandle_WaitHandle_ShouldThrowSshConnectionExceptionDetailingDisconnectReason()
         {
-            var session = (ISession)Session;
+            var session = (ISession) Session;
             var waitHandle = new ManualResetEvent(false);
 
             try
@@ -165,8 +166,36 @@ namespace Renci.SshNet.Tests.Classes
             {
                 Assert.AreEqual(DisconnectReason.ServiceNotAvailable, ex.DisconnectReason);
                 Assert.IsNull(ex.InnerException);
-                Assert.AreEqual(string.Format(CultureInfo.InvariantCulture, "The connection was closed by the server: {0} ({1}).", _disconnectMessage.Description, _disconnectMessage.ReasonCode), ex.Message);
+                Assert.AreEqual(string.Format(CultureInfo.InvariantCulture,
+                                              "The connection was closed by the server: {0} ({1}).",
+                                              _disconnectMessage.Description,
+                                              _disconnectMessage.ReasonCode),
+                                ex.Message);
             }
         }
+
+        [TestMethod]
+        public void ISession_TryWait_WaitHandleAndTimeout_ShouldReturnDisconnected()
+        {
+            var session = (ISession) Session;
+            var waitHandle = new ManualResetEvent(false);
+
+            var result = session.TryWait(waitHandle, Session.InfiniteTimeSpan);
+
+            Assert.AreEqual(WaitResult.Disconnected, result);
+        }
+
+        [TestMethod]
+        public void ISession_TryWait_WaitHandleAndTimeoutAndException_ShouldReturnDisconnected()
+        {
+            var session = (ISession) Session;
+            var waitHandle = new ManualResetEvent(false);
+            Exception exception;
+
+            var result = session.TryWait(waitHandle, Session.InfiniteTimeSpan, out exception);
+
+            Assert.AreEqual(WaitResult.Disconnected, result);
+            Assert.IsNull(exception);
+        }
     }
-}
+}

+ 236 - 0
src/Renci.SshNet.Tests/Classes/SessionTest_Connected_ServerSendsUnsupportedMessageType.cs

@@ -0,0 +1,236 @@
+using System;
+using System.Diagnostics;
+using System.Net.Sockets;
+using System.Threading;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Renci.SshNet.Common;
+using Renci.SshNet.Messages.Transport;
+
+namespace Renci.SshNet.Tests.Classes
+{
+    /// <summary>
+    /// This test verifies the current behavior, but this is not necessarily the behavior we want.
+    /// We should consider treating any exception as a "disconnect" since we're effectively interrupting
+    /// the message loop.
+    /// </summary>
+    [TestClass]
+    public class SessionTest_Connected_ServerSendsUnsupportedMessageType : SessionTest_ConnectedBase
+    {
+        private byte[] _packet;
+
+        protected override void SetupData()
+        {
+            base.SetupData();
+
+            _packet = CreatePacketForUnsupportedMessageType();
+        }
+
+        protected override void Act()
+        {
+            ServerSocket.Send(_packet, 0, _packet.Length, SocketFlags.None);
+
+            // give session some time to process packet
+            Thread.Sleep(200);
+        }
+
+        [TestMethod]
+        public void IsConnectedShouldReturnFalse()
+        {
+            Assert.IsFalse(Session.IsConnected);
+        }
+
+        [TestMethod]
+        public void DisconnectShouldFinishImmediately()
+        {
+            var stopwatch = new Stopwatch();
+            stopwatch.Start();
+
+            Session.Disconnect();
+
+            stopwatch.Stop();
+            Assert.IsTrue(stopwatch.ElapsedMilliseconds < 500);
+        }
+
+        [TestMethod]
+        public void DisconnectedIsNeverRaised()
+        {
+            Assert.AreEqual(0, DisconnectedRegister.Count);
+        }
+
+        [TestMethod]
+        public void DisconnectReceivedIsNeverRaised()
+        {
+            Assert.AreEqual(0, DisconnectReceivedRegister.Count);
+        }
+
+        [TestMethod]
+        public void ErrorOccurredIsRaisedOnce()
+        {
+            Assert.AreEqual(1, ErrorOccurredRegister.Count);
+
+            var errorOccurred = ErrorOccurredRegister[0];
+            Assert.IsNotNull(errorOccurred);
+
+            var exception = errorOccurred.Exception;
+            Assert.IsNotNull(exception);
+            Assert.AreEqual(typeof(SshException), exception.GetType());
+
+            var sshException = (SshException) exception;
+            Assert.IsNull(sshException.InnerException);
+            Assert.AreEqual("Message type 255 is not supported.", sshException.Message);
+        }
+
+        [TestMethod]
+        public void DisposeShouldFinishImmediately()
+        {
+            var stopwatch = new Stopwatch();
+            stopwatch.Start();
+
+            Session.Dispose();
+
+            stopwatch.Stop();
+            Assert.IsTrue(stopwatch.ElapsedMilliseconds < 500);
+        }
+
+        [TestMethod]
+        public void ReceiveOnServerSocketShouldTimeout()
+        {
+            var buffer = new byte[1];
+
+            ServerSocket.ReceiveTimeout = 500;
+            try
+            {
+                ServerSocket.Receive(buffer, 0, buffer.Length, SocketFlags.None);
+                Assert.Fail();
+            }
+            catch (SocketException ex)
+            {
+                Assert.AreEqual(SocketError.TimedOut, ex.SocketErrorCode);
+            }
+        }
+
+        [TestMethod]
+        public void SendMessageShouldSendMessageToServer()
+        {
+            byte[] bytesReceivedByServer = null;
+            ServerListener.BytesReceived += (received, socket) => bytesReceivedByServer = received;
+
+            Session.SendMessage(new IgnoreMessage());
+
+            // allow "server" some time to receive message
+            Thread.Sleep(100);
+
+            Assert.IsNotNull(bytesReceivedByServer);
+            Assert.AreEqual(24, bytesReceivedByServer.Length);
+        }
+
+        [TestMethod]
+        public void ISession_MessageListenerCompletedShouldBeSignaled()
+        {
+            var session = (ISession) Session;
+
+            Assert.IsNotNull(session.MessageListenerCompleted);
+            Assert.IsTrue(session.MessageListenerCompleted.WaitOne());
+        }
+
+        [TestMethodAttribute]
+        public void ISession_SendMessageShouldSendMessageToServer()
+        {
+            var session = (ISession) Session;
+
+            byte[] bytesReceivedByServer = null;
+            ServerListener.BytesReceived += (received, socket) => bytesReceivedByServer = received;
+
+            session.SendMessage(new IgnoreMessage());
+
+            // allow "server" some time to receive message
+            Thread.Sleep(100);
+
+            Assert.IsNotNull(bytesReceivedByServer);
+            Assert.AreEqual(24, bytesReceivedByServer.Length);
+        }
+
+        [TestMethod]
+        public void ISession_TrySendMessageShouldReturnTrueAndSendMessageToServer()
+        {
+            var session = (ISession) Session;
+
+            byte[] bytesReceivedByServer = null;
+            ServerListener.BytesReceived += (received, socket) => bytesReceivedByServer = received;
+
+            var actual = session.TrySendMessage(new IgnoreMessage());
+
+            Assert.IsTrue(actual);
+
+            // allow "server" some time to receive message
+            Thread.Sleep(100);
+
+            Assert.IsNotNull(bytesReceivedByServer);
+            Assert.AreEqual(24, bytesReceivedByServer.Length);
+        }
+
+        [TestMethod]
+        public void ISession_WaitOnHandleShouldThrowSshExceptionDetailingError()
+        {
+            var session = (ISession) Session;
+            var waitHandle = new ManualResetEvent(false);
+
+            try
+            {
+                session.WaitOnHandle(waitHandle);
+                Assert.Fail();
+            }
+            catch (SshException ex)
+            {
+                Assert.IsNull(ex.InnerException);
+                Assert.AreEqual("Message type 255 is not supported.", ex.Message);
+            }
+        }
+
+        [TestMethod]
+        public void ISession_TryWait_WaitHandleAndTimeout_ShouldReturnFailed()
+        {
+            var session = (ISession) Session;
+            var waitHandle = new ManualResetEvent(false);
+
+            var result = session.TryWait(waitHandle, Session.InfiniteTimeSpan);
+
+            Assert.AreEqual(WaitResult.Failed, result);
+        }
+
+        [TestMethod]
+        public void ISession_TryWait_WaitHandleAndTimeoutAndException_ShouldReturnFailed()
+        {
+            var session = (ISession) Session;
+            var waitHandle = new ManualResetEvent(false);
+            Exception exception;
+
+            var result = session.TryWait(waitHandle, Session.InfiniteTimeSpan, out exception);
+
+            Assert.AreEqual(WaitResult.Failed, result);
+            Assert.IsNotNull(exception);
+            Assert.AreEqual(typeof(SshException), exception.GetType());
+
+            var sshException = exception as SshException;
+            Assert.IsNotNull(sshException);
+            Assert.IsNull(sshException.InnerException);
+            Assert.AreEqual("Message type 255 is not supported.", sshException.Message);
+        }
+
+        private static byte[] CreatePacketForUnsupportedMessageType()
+        {
+            byte messageType = 255;
+            byte messageLength = 1;
+            byte paddingLength = 10;
+            var packetDataLength = (uint) messageLength + paddingLength + 1;
+
+            var sshDataStream = new SshDataStream(4 + 1 + messageLength + paddingLength);
+            sshDataStream.Write(packetDataLength);
+            sshDataStream.WriteByte(paddingLength);
+            sshDataStream.WriteByte(messageType);
+            sshDataStream.Write(new byte[paddingLength]);
+
+            return sshDataStream.ToArray();
+        }
+    }
+}

+ 45 - 2
src/Renci.SshNet.Tests/Classes/SessionTest_Connected_ServerShutsDownSendAfterSendingIncompletePacket.cs

@@ -146,7 +146,7 @@ namespace Renci.SshNet.Tests.Classes
         }
 
         [TestMethod]
-        public void ISession_WaitOnHandleShouldThrowSshConnectionExceptionDetailingBadPacket()
+        public void ISession_WaitOnHandle_WaitHandle_ShouldThrowSshConnectionExceptionDetailingBadPacket()
         {
             var session = (ISession) Session;
             var waitHandle = new ManualResetEvent(false);
@@ -163,5 +163,48 @@ namespace Renci.SshNet.Tests.Classes
                 Assert.AreEqual("An established connection was aborted by the server.", ex.Message);
             }
         }
+
+        [TestMethod]
+        public void ISession_WaitOnHandle_WaitHandleAndTimeout_ShouldThrowSshConnectionExceptionDetailingBadPacket()
+        {
+            var session = (ISession) Session;
+            var waitHandle = new ManualResetEvent(false);
+
+            try
+            {
+                session.WaitOnHandle(waitHandle, Session.InfiniteTimeSpan);
+                Assert.Fail();
+            }
+            catch (SshConnectionException ex)
+            {
+                Assert.AreEqual(DisconnectReason.ConnectionLost, ex.DisconnectReason);
+                Assert.IsNull(ex.InnerException);
+                Assert.AreEqual("An established connection was aborted by the server.", ex.Message);
+            }
+        }
+
+        [TestMethod]
+        public void ISession_TryWait_WaitHandleAndTimeout_ShouldReturnDisconnected()
+        {
+            var session = (ISession) Session;
+            var waitHandle = new ManualResetEvent(false);
+
+            var result = session.TryWait(waitHandle, Session.InfiniteTimeSpan);
+
+            Assert.AreEqual(WaitResult.Disconnected, result);
+        }
+
+        [TestMethod]
+        public void ISession_TryWait_WaitHandleAndTimeoutAndException_ShouldReturnDisconnected()
+        {
+            var session = (ISession) Session;
+            var waitHandle = new ManualResetEvent(false);
+            Exception exception;
+
+            var result = session.TryWait(waitHandle, Session.InfiniteTimeSpan, out exception);
+
+            Assert.AreEqual(WaitResult.Disconnected, result);
+            Assert.IsNull(exception);
+        }
     }
-}
+}

+ 90 - 6
src/Renci.SshNet.Tests/Classes/SessionTest_Connected_ServerShutsDownSocket.cs

@@ -1,4 +1,5 @@
-using System.Diagnostics;
+using System;
+using System.Diagnostics;
 using System.Net.Sockets;
 using System.Threading;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
@@ -107,7 +108,7 @@ namespace Renci.SshNet.Tests.Classes
         [TestMethod]
         public void ISession_MessageListenerCompletedShouldBeSignaled()
         {
-            var session = (ISession)Session;
+            var session = (ISession) Session;
 
             Assert.IsNotNull(session.MessageListenerCompleted);
             Assert.IsTrue(session.MessageListenerCompleted.WaitOne());
@@ -133,7 +134,7 @@ namespace Renci.SshNet.Tests.Classes
         [TestMethod]
         public void ISession_TrySendMessageShouldReturnFalse()
         {
-            var session = (ISession)Session;
+            var session = (ISession) Session;
 
             var actual = session.TrySendMessage(new IgnoreMessage());
 
@@ -141,9 +142,9 @@ namespace Renci.SshNet.Tests.Classes
         }
 
         [TestMethod]
-        public void ISession_WaitOnHandleShouldThrowSshConnectionExceptionDetailingAbortedConnection()
+        public void ISession_WaitOnHandle_WaitHandle_ShouldThrowSshConnectionExceptionDetailingAbortedConnection()
         {
-            var session = (ISession)Session;
+            var session = (ISession) Session;
             var waitHandle = new ManualResetEvent(false);
 
             try
@@ -157,5 +158,88 @@ namespace Renci.SshNet.Tests.Classes
                 Assert.AreEqual("An established connection was aborted by the server.", ex.Message);
             }
         }
+
+        [TestMethod]
+        public void ISession_WaitOnHandle_WaitHandleAndTimeout_ShouldThrowSshConnectionExceptionDetailingAbortedConnection()
+        {
+            var session = (ISession) Session;
+            var waitHandle = new ManualResetEvent(false);
+
+            try
+            {
+                session.WaitOnHandle(waitHandle, Session.InfiniteTimeSpan);
+                Assert.Fail();
+            }
+            catch (SshConnectionException ex)
+            {
+                Assert.IsNull(ex.InnerException);
+                Assert.AreEqual("An established connection was aborted by the server.", ex.Message);
+            }
+        }
+
+        [TestMethod]
+        public void ISession_TryWait_WaitHandleAndTimeout_ShouldReturnDisconnected()
+        {
+            var session = (ISession) Session;
+            var waitHandle = new ManualResetEvent(false);
+
+            var result = session.TryWait(waitHandle, Session.InfiniteTimeSpan);
+
+            Assert.AreEqual(WaitResult.Disconnected, result);
+        }
+
+        [TestMethod]
+        public void ISession_TryWait_WaitHandleAndTimeout_ShouldThrowArgumentNullExceptionWhenWaitHandleIsNull()
+        {
+            var session = (ISession) Session;
+            const WaitHandle waitHandle = null;
+            var timeout = TimeSpan.FromMinutes(5);
+
+            try
+            {
+                session.TryWait(waitHandle, timeout);
+                Assert.Fail();
+            }
+            catch (ArgumentNullException ex)
+            {
+                Assert.IsNull(ex.InnerException);
+                Assert.AreEqual("waitHandle", ex.ParamName);
+            }
+        }
+
+        [TestMethod]
+        public void ISession_TryWait_WaitHandleAndTimeoutAndException_ShouldReturnDisconnected()
+        {
+            var session = (ISession) Session;
+            var waitHandle = new ManualResetEvent(false);
+            Exception exception;
+
+            var result = session.TryWait(waitHandle, Session.InfiniteTimeSpan, out exception);
+
+            Assert.AreEqual(WaitResult.Disconnected, result);
+            Assert.IsNull(exception);
+        }
+
+        [TestMethod]
+        public void ISession_TryWait_WaitHandleAndTimeoutAndException_ShouldThrowArgumentNullExceptionWhenWaitHandleIsNull()
+        {
+            var session = (ISession) Session;
+            const WaitHandle waitHandle = null;
+            var timeout = TimeSpan.FromMinutes(5);
+            Exception exception = null;
+
+            try
+            {
+                session.TryWait(waitHandle, timeout, out exception);
+                Assert.Fail();
+            }
+            catch (ArgumentNullException ex)
+            {
+                Assert.IsNull(ex.InnerException);
+                Assert.AreEqual("waitHandle", ex.ParamName);
+            }
+
+            Assert.IsNull(exception);
+        }
     }
-}
+}

+ 53 - 11
src/Renci.SshNet.Tests/Classes/SessionTest_NotConnected.cs

@@ -81,9 +81,9 @@ namespace Renci.SshNet.Tests.Classes
         }
 
         [TestMethod]
-        public void WaitOnHandle_WaitHandle_ShouldThrowArgumentNullExceptionWhenWaitHandleIsNull()
+        public void WaitOnHandle_WaitOnHandle_WaitHandle_ShouldThrowArgumentNullExceptionWhenWaitHandleIsNull()
         {
-            WaitHandle waitHandle = null;
+            const WaitHandle waitHandle = null;
 
             try
             {
@@ -98,9 +98,9 @@ namespace Renci.SshNet.Tests.Classes
         }
 
         [TestMethod]
-        public void WaitOnHandle_WaitHandleAndTimeout_ShouldThrowArgumentNullExceptionWhenWaitHandleIsNull()
+        public void WaitOnHandle_WaitOnHandle_WaitHandleAndTimeout_ShouldThrowArgumentNullExceptionWhenWaitHandleIsNull()
         {
-            WaitHandle waitHandle = null;
+            const WaitHandle waitHandle = null;
             var timeout = TimeSpan.FromMinutes(5);
 
             try
@@ -115,10 +115,34 @@ namespace Renci.SshNet.Tests.Classes
             }
         }
 
+        [TestMethod]
+        public void ISession_TryWait_WaitHandleAndTimeout_ShouldReturnDisconnected()
+        {
+            var session = (ISession) _session;
+            var waitHandle = new ManualResetEvent(false);
+
+            var result = session.TryWait(waitHandle, Session.InfiniteTimeSpan);
+
+            Assert.AreEqual(WaitResult.Disconnected, result);
+        }
+
+        [TestMethod]
+        public void ISession_TryWait_WaitHandleAndTimeoutAndException_ShouldReturnDisconnected()
+        {
+            var session = (ISession) _session;
+            var waitHandle = new ManualResetEvent(false);
+            Exception exception;
+
+            var result = session.TryWait(waitHandle, Session.InfiniteTimeSpan, out exception);
+
+            Assert.AreEqual(WaitResult.Disconnected, result);
+            Assert.IsNull(exception);
+        }
+
         [TestMethod]
         public void ISession_ConnectionInfoShouldReturnConnectionInfoPassedThroughConstructor()
         {
-            var session = (ISession)_session;
+            var session = (ISession) _session;
             Assert.AreSame(_connectionInfo, session.ConnectionInfo);
         }
 
@@ -134,7 +158,7 @@ namespace Renci.SshNet.Tests.Classes
         [TestMethod]
         public void ISession_SendMessageShouldThrowShhConnectionException()
         {
-            var session = (ISession)_session;
+            var session = (ISession) _session;
 
             try
             {
@@ -152,7 +176,7 @@ namespace Renci.SshNet.Tests.Classes
         [TestMethod]
         public void ISession_TrySendMessageShouldReturnFalse()
         {
-            var session = (ISession)_session;
+            var session = (ISession) _session;
 
             var actual = session.TrySendMessage(new IgnoreMessage());
 
@@ -160,10 +184,10 @@ namespace Renci.SshNet.Tests.Classes
         }
 
         [TestMethod]
-        public void ISession_WaitOnHandleShouldThrowArgumentNullExceptionWhenWaitHandleIsNull()
+        public void ISession_WaitOnHandle_WaitHandle_ShouldThrowArgumentNullExceptionWhenWaitHandleIsNull()
         {
-            WaitHandle waitHandle = null;
-            var session = (ISession)_session;
+            const WaitHandle waitHandle = null;
+            var session = (ISession) _session;
 
             try
             {
@@ -177,6 +201,24 @@ namespace Renci.SshNet.Tests.Classes
             }
         }
 
+        [TestMethod]
+        public void ISession_WaitOnHandle_WaitHandleAndTimeout_ShouldThrowArgumentNullExceptionWhenWaitHandleIsNull()
+        {
+            const WaitHandle waitHandle = null;
+            var session = (ISession) _session;
+
+            try
+            {
+                session.WaitOnHandle(waitHandle, Session.InfiniteTimeSpan);
+                Assert.Fail();
+            }
+            catch (ArgumentNullException ex)
+            {
+                Assert.IsNull(ex.InnerException);
+                Assert.AreEqual("waitHandle", ex.ParamName);
+            }
+        }
+
         private static ConnectionInfo CreateConnectionInfo(IPEndPoint serverEndPoint, TimeSpan timeout)
         {
             var connectionInfo = new ConnectionInfo(
@@ -188,4 +230,4 @@ namespace Renci.SshNet.Tests.Classes
             return connectionInfo;
         }
     }
-}
+}

+ 8 - 23
src/Renci.SshNet/Channels/Channel.cs

@@ -5,6 +5,7 @@ using Renci.SshNet.Common;
 using Renci.SshNet.Messages;
 using Renci.SshNet.Messages.Connection;
 using System.Globalization;
+using Renci.SshNet.Abstractions;
 
 namespace Renci.SshNet.Channels
 {
@@ -15,7 +16,6 @@ namespace Renci.SshNet.Channels
     {
         private EventWaitHandle _channelClosedWaitHandle = new ManualResetEvent(false);
         private EventWaitHandle _channelServerWindowAdjustWaitHandle = new ManualResetEvent(false);
-        private EventWaitHandle _errorOccuredWaitHandle = new ManualResetEvent(false);
         private readonly object _serverWindowSizeLock = new object();
         private readonly uint _initialWindowSize;
         private uint? _remoteWindowSize;
@@ -327,11 +327,10 @@ namespace Renci.SshNet.Channels
             {
                 var sizeOfCurrentMessage = GetDataLengthThatCanBeSentInMessage(totalBytesToSend);
 
-                var channelDataMessage = new ChannelDataMessage(
-                    RemoteChannelNumber,
-                    data,
-                    offset,
-                    sizeOfCurrentMessage);
+                var channelDataMessage = new ChannelDataMessage(RemoteChannelNumber,
+                                                                data,
+                                                                offset,
+                                                                sizeOfCurrentMessage);
                 _session.SendMessage(channelDataMessage);
 
                 totalBytesToSend -= sizeOfCurrentMessage;
@@ -549,13 +548,10 @@ namespace Renci.SshNet.Channels
                         // only wait for the channel to be closed by the server if we didn't send a
                         // SSH_MSG_CHANNEL_CLOSE as response to a SSH_MSG_CHANNEL_CLOSE sent by the
                         // server
-                        try
+                        var closeWaitResult = _session.TryWait(_channelClosedWaitHandle, ConnectionInfo.ChannelCloseTimeout);
+                        if (closeWaitResult != WaitResult.Success)
                         {
-                            WaitOnHandle(_channelClosedWaitHandle);
-                        }
-                        catch (SshConnectionException)
-                        {
-                            // ignore connection failures as we're closing the channel anyway
+                            DiagnosticAbstraction.Log(string.Format("Wait for channel close not successful: {0:G}.", closeWaitResult));
                         }
                     }
                 }
@@ -620,10 +616,6 @@ namespace Renci.SshNet.Channels
             try
             {
                 OnErrorOccured(e.Exception);
-
-                var errorOccuredWaitHandle = _errorOccuredWaitHandle;
-                if (errorOccuredWaitHandle != null)
-                    errorOccuredWaitHandle.Set();
             }
             catch (Exception ex)
             {
@@ -879,13 +871,6 @@ namespace Renci.SshNet.Channels
                     channelServerWindowAdjustWaitHandle.Dispose();
                 }
 
-                var errorOccuredWaitHandle = _errorOccuredWaitHandle;
-                if (errorOccuredWaitHandle != null)
-                {
-                    _errorOccuredWaitHandle = null;
-                    errorOccuredWaitHandle.Dispose();
-                }
-
                 _isDisposed = true;
             }
         }

+ 30 - 1
src/Renci.SshNet/ConnectionInfo.cs

@@ -23,6 +23,22 @@ namespace Renci.SshNet
     {
         internal static int DefaultPort = 22;
 
+        /// <summary>
+        /// The default connection timeout.
+        /// </summary>
+        /// <value>
+        /// 30 seconds.
+        /// </value>
+        private static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(30);
+
+        /// <summary>
+        /// The default channel close timeout.
+        /// </summary>
+        /// <value>
+        /// 1 second.
+        /// </value>
+        private static readonly TimeSpan DefaultChannelCloseTimeout = TimeSpan.FromSeconds(1);
+
         /// <summary>
         /// Gets supported key exchange algorithms for this connection.
         /// </summary>
@@ -126,6 +142,18 @@ namespace Renci.SshNet
         /// </example>
         public TimeSpan Timeout { get; set; }
 
+        /// <summary>
+        /// Gets or sets the timeout to used when waiting for a server to acknowledge closing a channel.
+        /// </summary>
+        /// <value>
+        /// The channel close timeout. The default value is 1 second.
+        /// </value>
+        /// <remarks>
+        /// If a server does not send a <c>SSH2_MSG_CHANNEL_CLOSE</c> message before the specified timeout
+        /// elapses, the channel will be closed immediately.
+        /// </remarks>
+        public TimeSpan ChannelCloseTimeout { get; set; }
+
         /// <summary>
         /// Gets or sets the character encoding.
         /// </summary>
@@ -286,7 +314,8 @@ namespace Renci.SshNet
                 throw new ArgumentException("At least one authentication method should be specified.", "authenticationMethods");
 
             //  Set default connection values
-            Timeout = TimeSpan.FromSeconds(30);
+            Timeout = DefaultTimeout;
+            ChannelCloseTimeout = DefaultChannelCloseTimeout;
             RetryAttempts = 10;
             MaxSessions = 10;
             Encoding = Encoding.UTF8;

+ 12 - 0
src/Renci.SshNet/IConnectionInfo.cs

@@ -40,6 +40,18 @@ namespace Renci.SshNet
     /// </summary>
     internal interface IConnectionInfo
     {
+        /// <summary>
+        /// Gets or sets the timeout to used when waiting for a server to acknowledge closing a channel.
+        /// </summary>
+        /// <value>
+        /// The channel close timeout. The default value is 1 second.
+        /// </value>
+        /// <remarks>
+        /// If a server does not send a <c>SSH2_MSG_CHANNEL_CLOSE</c> message before the specified timeout
+        /// elapses, the channel will be closed immediately.
+        /// </remarks>
+        TimeSpan ChannelCloseTimeout { get; }
+
         /// <summary>
         /// Gets the supported channel requests for this connection.
         /// </summary>

+ 4 - 0
src/Renci.SshNet/ISession.cs

@@ -156,6 +156,10 @@ namespace Renci.SshNet
         /// </remarks>
         void WaitOnHandle(WaitHandle waitHandle, TimeSpan timeout);
 
+        WaitResult TryWait(WaitHandle waitHandle, TimeSpan timeout, out Exception exception);
+
+        WaitResult TryWait(WaitHandle waitHandle, TimeSpan timeout);
+
         /// <summary>
         /// Occurs when <see cref="ChannelCloseMessage"/> message received
         /// </summary>

+ 59 - 3
src/Renci.SshNet/Session.cs

@@ -798,6 +798,53 @@ namespace Renci.SshNet
             WaitOnHandle(waitHandle, ConnectionInfo.Timeout);
         }
 
+        WaitResult ISession.TryWait(WaitHandle waitHandle, TimeSpan timeout)
+        {
+            Exception exception;
+            return TryWait(waitHandle, timeout, out exception);
+        }
+
+        WaitResult ISession.TryWait(WaitHandle waitHandle, TimeSpan timeout, out Exception exception)
+        {
+            return TryWait(waitHandle, timeout, out exception);
+        }
+
+        private WaitResult TryWait(WaitHandle waitHandle, TimeSpan timeout, out Exception exception)
+        {
+            if (waitHandle == null)
+                throw new ArgumentNullException("waitHandle");
+
+            var waitHandles = new[]
+                {
+                    _exceptionWaitHandle,
+                    _messageListenerCompleted,
+                    waitHandle
+                };
+
+            switch (WaitHandle.WaitAny(waitHandles, timeout))
+            {
+                case 0:
+                    if (_exception is SshConnectionException)
+                    {
+                        exception = null;
+                        return WaitResult.Disconnected;
+                    }
+                    exception = _exception;
+                    return WaitResult.Failed;
+                case 1:
+                    exception = null;
+                    return WaitResult.Disconnected;
+                case 2:
+                    exception = null;
+                    return WaitResult.Success;
+                case WaitHandle.WaitTimeout:
+                    exception = null;
+                    return WaitResult.TimedOut;
+                default:
+                    throw new InvalidOperationException("Unexpected result.");
+            }
+        }
+
         /// <summary>
         /// Waits for the specified handle or the exception handle for the receive thread
         /// to signal within the specified timeout.
@@ -1077,7 +1124,7 @@ namespace Renci.SshNet
                 var serverHash = data.Take(data.Length - serverMacLength, serverMacLength);
 
                 // TODO add IsEqualTo overload that takes left+right index and number of bytes to compare;
-                // TODO that way we can eliminate the extrate allocation of the Take above
+                // TODO that way we can eliminate the extra allocation of the Take above
                 if (!serverHash.IsEqualTo(clientHash))
                 {
                     throw new SshConnectionException("MAC error", DisconnectReason.MacError);
@@ -2412,8 +2459,9 @@ namespace Renci.SshNet
         /// <returns>
         /// A new "forwarded-tcpip" SSH channel.
         /// </returns>
-        IChannelForwardedTcpip ISession.CreateChannelForwardedTcpip(uint remoteChannelNumber, uint remoteWindowSize,
-            uint remoteChannelDataPacketSize)
+        IChannelForwardedTcpip ISession.CreateChannelForwardedTcpip(uint remoteChannelNumber,
+                                                                    uint remoteWindowSize,
+                                                                    uint remoteChannelDataPacketSize)
         {
             return new ChannelForwardedTcpip(this,
                                              NextChannelNumber,
@@ -2455,4 +2503,12 @@ namespace Renci.SshNet
 
 #endregion ISession implementation
     }
+
+    internal enum WaitResult
+    {
+        Success = 1,
+        TimedOut = 2,
+        Disconnected = 3,
+        Failed = 4
+    }
 }