|
|
@@ -0,0 +1,137 @@
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Diagnostics;
|
|
|
+using System.Threading;
|
|
|
+using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
|
+using Moq;
|
|
|
+using Renci.SshNet.Common;
|
|
|
+using Renci.SshNet.Messages.Connection;
|
|
|
+
|
|
|
+namespace Renci.SshNet.Tests.Classes.Channels
|
|
|
+{
|
|
|
+ [TestClass]
|
|
|
+ public class ChannelTest_Close_SessionIsConnectedAndChannelIsOpen_EofNotReceived_SendEofInvoked
|
|
|
+ {
|
|
|
+ private Mock<ISession> _sessionMock;
|
|
|
+ private uint _localChannelNumber;
|
|
|
+ private uint _localWindowSize;
|
|
|
+ private uint _localPacketSize;
|
|
|
+ private uint _remoteChannelNumber;
|
|
|
+ private uint _remoteWindowSize;
|
|
|
+ private uint _remotePacketSize;
|
|
|
+ private ChannelStub _channel;
|
|
|
+ private Stopwatch _closeTimer;
|
|
|
+ private List<ChannelEventArgs> _channelClosedRegister;
|
|
|
+ private IList<ExceptionEventArgs> _channelExceptionRegister;
|
|
|
+
|
|
|
+ [TestInitialize]
|
|
|
+ public void Initialize()
|
|
|
+ {
|
|
|
+ Arrange();
|
|
|
+ Act();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void Arrange()
|
|
|
+ {
|
|
|
+ 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);
|
|
|
+ _closeTimer = new Stopwatch();
|
|
|
+ _channelClosedRegister = new List<ChannelEventArgs>();
|
|
|
+ _channelExceptionRegister = new List<ExceptionEventArgs>();
|
|
|
+
|
|
|
+ _sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
|
|
+
|
|
|
+ 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);
|
|
|
+ _channel.Closed += (sender, args) => _channelClosedRegister.Add(args);
|
|
|
+ _channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
|
|
|
+ _channel.InitializeRemoteChannelInfo(_remoteChannelNumber, _remoteWindowSize, _remotePacketSize);
|
|
|
+ _channel.SetIsOpen(true);
|
|
|
+ _channel.SendEof();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void Act()
|
|
|
+ {
|
|
|
+ _channel.Close();
|
|
|
+ }
|
|
|
+
|
|
|
+ [TestMethod]
|
|
|
+ public void IsOpenShouldReturnFalse()
|
|
|
+ {
|
|
|
+ Assert.IsFalse(_channel.IsOpen);
|
|
|
+ }
|
|
|
+
|
|
|
+ [TestMethod]
|
|
|
+ public void TrySendMessageOnSessionShouldBeInvokedOnceForChannelCloseMessage()
|
|
|
+ {
|
|
|
+ _sessionMock.Verify(
|
|
|
+ p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)),
|
|
|
+ Times.Once);
|
|
|
+ }
|
|
|
+
|
|
|
+ [TestMethod]
|
|
|
+ public void SendMessageOnSessionShouldBeInvokedOnceForChannelEofMessage()
|
|
|
+ {
|
|
|
+ _sessionMock.Verify(
|
|
|
+ p => p.SendMessage(It.Is<ChannelEofMessage>(c => c.LocalChannelNumber == _remoteChannelNumber)),
|
|
|
+ Times.Once);
|
|
|
+ }
|
|
|
+
|
|
|
+ [TestMethod]
|
|
|
+ public void WaitOnHandleOnSessionShouldBeInvokedOnce()
|
|
|
+ {
|
|
|
+ _sessionMock.Verify(p => p.WaitOnHandle(It.IsAny<EventWaitHandle>()), Times.Once);
|
|
|
+ }
|
|
|
+
|
|
|
+ [TestMethod]
|
|
|
+ public void WaitOnHandleOnSessionShouldWaitForChannelCloseMessageToBeReceived()
|
|
|
+ {
|
|
|
+ Assert.IsTrue(_closeTimer.ElapsedMilliseconds >= 100, "Elapsed milliseconds=" + _closeTimer.ElapsedMilliseconds);
|
|
|
+ }
|
|
|
+
|
|
|
+ [TestMethod]
|
|
|
+ public void ClosedEventShouldHaveFiredOnce()
|
|
|
+ {
|
|
|
+ Assert.AreEqual(1, _channelClosedRegister.Count);
|
|
|
+ Assert.AreEqual(_localChannelNumber, _channelClosedRegister[0].ChannelNumber);
|
|
|
+ }
|
|
|
+
|
|
|
+ [TestMethod]
|
|
|
+ public void ExceptionShouldNeverHaveFired()
|
|
|
+ {
|
|
|
+ Assert.AreEqual(0, _channelExceptionRegister.Count);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|