mirror of
https://github.com/sshnet/SSH.NET.git
synced 2026-09-10 01:05:42 +00:00
When the request to open a subsystem fails, close the channel session and throw a SshException.
Fixes #308.
This commit is contained in:
@@ -1551,6 +1551,9 @@
|
||||
<Compile Include="..\Renci.SshNet.Tests\Classes\SubsystemSession_Connect_NeverConnected.cs">
|
||||
<Link>Classes\SubsystemSession_Connect_NeverConnected.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Renci.SshNet.Tests\Classes\SubsystemSession_Connect_SendSubsystemRequestFails.cs">
|
||||
<Link>Classes\SubsystemSession_Connect_SendSubsystemRequestFails.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Renci.SshNet.Tests\Classes\SubsystemSession_Disconnect_Connected.cs">
|
||||
<Link>Classes\SubsystemSession_Disconnect_Connected.cs</Link>
|
||||
</Compile>
|
||||
@@ -1707,7 +1710,7 @@
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<UserProperties ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" ProjectLinkReference="c45379b9-17b1-4e89-bc2e-6d41726413e8" />
|
||||
<UserProperties ProjectLinkReference="c45379b9-17b1-4e89-bc2e-6d41726413e8" ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" />
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Channels;
|
||||
using Renci.SshNet.Common;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class SubsystemSession_Connect_SendSubsystemRequestFails
|
||||
{
|
||||
private Mock<ISession> _sessionMock;
|
||||
private Mock<IChannelSession> _channelMock;
|
||||
private string _subsystemName;
|
||||
private SubsystemSessionStub _subsystemSession;
|
||||
private int _operationTimeout;
|
||||
private IList<EventArgs> _disconnectedRegister;
|
||||
private IList<ExceptionEventArgs> _errorOccurredRegister;
|
||||
private SshException _actualException;
|
||||
private MockSequence _sequence;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
}
|
||||
|
||||
protected void Arrange()
|
||||
{
|
||||
var random = new Random();
|
||||
_subsystemName = random.Next().ToString(CultureInfo.InvariantCulture);
|
||||
_operationTimeout = 30000;
|
||||
_disconnectedRegister = new List<EventArgs>();
|
||||
_errorOccurredRegister = new List<ExceptionEventArgs>();
|
||||
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
_channelMock = new Mock<IChannelSession>(MockBehavior.Strict);
|
||||
|
||||
_sequence = new MockSequence();
|
||||
_sessionMock.InSequence(_sequence).Setup(p => p.CreateChannelSession()).Returns(_channelMock.Object);
|
||||
_channelMock.InSequence(_sequence).Setup(p => p.Open());
|
||||
_channelMock.InSequence(_sequence).Setup(p => p.SendSubsystemRequest(_subsystemName)).Returns(false);
|
||||
_channelMock.InSequence(_sequence).Setup(p => p.Dispose());
|
||||
|
||||
_subsystemSession = new SubsystemSessionStub(_sessionMock.Object,
|
||||
_subsystemName,
|
||||
_operationTimeout);
|
||||
_subsystemSession.Disconnected += (sender, args) => _disconnectedRegister.Add(args);
|
||||
_subsystemSession.ErrorOccurred += (sender, args) => _errorOccurredRegister.Add(args);
|
||||
}
|
||||
|
||||
protected void Act()
|
||||
{
|
||||
try
|
||||
{
|
||||
_subsystemSession.Connect();
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException ex)
|
||||
{
|
||||
_actualException = ex;
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveThrownSshException()
|
||||
{
|
||||
Assert.IsNotNull(_actualException);
|
||||
Assert.IsNull(_actualException.InnerException);
|
||||
Assert.AreEqual(string.Format(CultureInfo.InvariantCulture, "Subsystem '{0}' could not be executed.", _subsystemName), _actualException.Message);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ChannelShouldBeNull()
|
||||
{
|
||||
Assert.IsNull(_subsystemSession.Channel);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DisconnectHasNeverFired()
|
||||
{
|
||||
Assert.AreEqual(0, _disconnectedRegister.Count);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ErrorOccurredHasNeverFired()
|
||||
{
|
||||
Assert.AreEqual(0, _errorOccurredRegister.Count);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IsOpenShouldReturnFalse()
|
||||
{
|
||||
Assert.IsFalse(_subsystemSession.IsOpen);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DisposeOnChannelShouldBeInvokedOnce()
|
||||
{
|
||||
_channelMock.Verify(p => p.Dispose(), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ErrorOccuredOnSessionShouldNoLongerBeSignaledViaErrorOccurredOnSubsystemSession()
|
||||
{
|
||||
_sessionMock.Raise(p => p.ErrorOccured += null, new ExceptionEventArgs(new Exception()));
|
||||
|
||||
Assert.AreEqual(0, _errorOccurredRegister.Count);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DisconnectedOnSessionShouldNoLongerBeSignaledViaDisconnectedOnSubsystemSession()
|
||||
{
|
||||
_sessionMock.Raise(p => p.Disconnected += null, new EventArgs());
|
||||
|
||||
Assert.AreEqual(0, _disconnectedRegister.Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -553,6 +553,7 @@
|
||||
<Compile Include="Classes\SubsystemSession_Connect_Disconnected.cs" />
|
||||
<Compile Include="Classes\SubsystemSession_Connect_Disposed.cs" />
|
||||
<Compile Include="Classes\SubsystemSession_Connect_NeverConnected.cs" />
|
||||
<Compile Include="Classes\SubsystemSession_Connect_SendSubsystemRequestFails.cs" />
|
||||
<Compile Include="Classes\SubsystemSession_Disconnect_Connected.cs" />
|
||||
<Compile Include="Classes\SubsystemSession_Disconnect_Disposed.cs" />
|
||||
<Compile Include="Classes\SubsystemSession_Disconnect_NeverConnected.cs" />
|
||||
|
||||
@@ -95,6 +95,7 @@ namespace Renci.SshNet
|
||||
/// </summary>
|
||||
/// <exception cref="InvalidOperationException">The session is already connected.</exception>
|
||||
/// <exception cref="ObjectDisposedException">The method was called after the session was disposed.</exception>
|
||||
/// <exception cref="SshException">The channel session could not be opened, or the subsystem could not be executed.</exception>
|
||||
public void Connect()
|
||||
{
|
||||
EnsureNotDisposed();
|
||||
@@ -116,7 +117,16 @@ namespace Renci.SshNet
|
||||
_channel.Exception += Channel_Exception;
|
||||
_channel.Closed += Channel_Closed;
|
||||
_channel.Open();
|
||||
_channel.SendSubsystemRequest(_subsystemName);
|
||||
|
||||
if (!_channel.SendSubsystemRequest(_subsystemName))
|
||||
{
|
||||
// close channel session
|
||||
Disconnect();
|
||||
// signal subsystem failure
|
||||
throw new SshException(string.Format(CultureInfo.InvariantCulture,
|
||||
"Subsystem '{0}' could not be executed.",
|
||||
_subsystemName));
|
||||
}
|
||||
|
||||
OnChannelOpen();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user