mirror of
https://github.com/sshnet/SSH.NET.git
synced 2026-09-10 09:15:47 +00:00
Complete refactoring of connection process, and greatly improve test coverage.
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
using Moq;
|
||||
using Renci.SshNet.Connection;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
public abstract class BaseClientTestBase : TripleATestBase
|
||||
{
|
||||
internal Mock<IServiceFactory> _serviceFactoryMock { get; private set; }
|
||||
internal Mock<ISocketFactory> _socketFactoryMock { get; private set; }
|
||||
internal Mock<ISession> _sessionMock { get; private set; }
|
||||
|
||||
protected virtual void CreateMocks()
|
||||
{
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_socketFactoryMock = new Mock<ISocketFactory>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
}
|
||||
|
||||
protected virtual void SetupData()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void SetupMocks()
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Arrange()
|
||||
{
|
||||
CreateMocks();
|
||||
SetupData();
|
||||
SetupMocks();
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
-35
@@ -9,24 +9,30 @@ using Renci.SshNet.Security;
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class BaseClientTest_Connect_OnConnectedThrowsException
|
||||
public class BaseClientTest_Connect_OnConnectedThrowsException : BaseClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private MyClient _client;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private ApplicationException _onConnectException;
|
||||
private ApplicationException _actualException;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
protected override void SetupData()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
_connectionInfo = new ConnectionInfo("host", "user", new PasswordAuthenticationMethod("user", "pwd"));
|
||||
_onConnectException = new ApplicationException();
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
_serviceFactoryMock.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.Setup(p => p.Connect());
|
||||
_sessionMock.Setup(p => p.Dispose());
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
if (_client != null)
|
||||
{
|
||||
@@ -36,31 +42,9 @@ namespace Renci.SshNet.Tests.Classes
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupData()
|
||||
protected override void Arrange()
|
||||
{
|
||||
_connectionInfo = new ConnectionInfo("host", "user", new PasswordAuthenticationMethod("user", "pwd"));
|
||||
_onConnectException = new ApplicationException();
|
||||
}
|
||||
|
||||
private void CreateMocks()
|
||||
{
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
}
|
||||
|
||||
private void SetupMocks()
|
||||
{
|
||||
_serviceFactoryMock.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.Setup(p => p.Connect());
|
||||
_sessionMock.Setup(p => p.Dispose());
|
||||
}
|
||||
|
||||
protected void Arrange()
|
||||
{
|
||||
SetupData();
|
||||
CreateMocks();
|
||||
SetupMocks();
|
||||
base.Arrange();
|
||||
|
||||
_client = new MyClient(_connectionInfo, false, _serviceFactoryMock.Object)
|
||||
{
|
||||
@@ -68,7 +52,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
};
|
||||
}
|
||||
|
||||
protected void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -88,10 +72,17 @@ namespace Renci.SshNet.Tests.Classes
|
||||
Assert.AreSame(_onConnectException, _actualException);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSocketFactoryOnServiceFactoryShouldBeInvokedOnce()
|
||||
{
|
||||
_serviceFactoryMock.Verify(p => p.CreateSocketFactory(), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSessionOnServiceFactoryShouldBeInvokedOnce()
|
||||
{
|
||||
_serviceFactoryMock.Verify(p => p.CreateSession(_connectionInfo), Times.Once);
|
||||
_serviceFactoryMock.Verify(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
+37
-46
@@ -2,29 +2,49 @@
|
||||
using System.Threading;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Connection;
|
||||
using Renci.SshNet.Messages.Transport;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class BaseClientTest_Connected_KeepAliveInterval_NegativeOne
|
||||
public class BaseClientTest_Connected_KeepAliveInterval_NegativeOne : BaseClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private BaseClient _client;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private TimeSpan _keepAliveInterval;
|
||||
private int _keepAliveCount;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
protected override void SetupData()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
_connectionInfo = new ConnectionInfo("host", "user", new PasswordAuthenticationMethod("user", "pwd"));
|
||||
_keepAliveInterval = TimeSpan.FromMilliseconds(100d);
|
||||
_keepAliveCount = 0;
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
_serviceFactoryMock.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.Setup(p => p.Connect());
|
||||
_sessionMock.Setup(p => p.IsConnected).Returns(true);
|
||||
_sessionMock.Setup(p => p.TrySendMessage(It.IsAny<IgnoreMessage>()))
|
||||
.Returns(true)
|
||||
.Callback(() => Interlocked.Increment(ref _keepAliveCount));
|
||||
}
|
||||
|
||||
protected override void Arrange()
|
||||
{
|
||||
base.Arrange();
|
||||
|
||||
_client = new MyClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
_client.Connect();
|
||||
_client.KeepAliveInterval = _keepAliveInterval;
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
if (_client != null)
|
||||
{
|
||||
@@ -34,42 +54,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupData()
|
||||
{
|
||||
_connectionInfo = new ConnectionInfo("host", "user", new PasswordAuthenticationMethod("user", "pwd"));
|
||||
_keepAliveInterval = TimeSpan.FromMilliseconds(100d);
|
||||
_keepAliveCount = 0;
|
||||
}
|
||||
|
||||
private void CreateMocks()
|
||||
{
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
}
|
||||
|
||||
private void SetupMocks()
|
||||
{
|
||||
_serviceFactoryMock.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.Setup(p => p.Connect());
|
||||
_sessionMock.Setup(p => p.IsConnected).Returns(true);
|
||||
_sessionMock.Setup(p => p.TrySendMessage(It.IsAny<IgnoreMessage>()))
|
||||
.Returns(true)
|
||||
.Callback(() => Interlocked.Increment(ref _keepAliveCount));
|
||||
}
|
||||
|
||||
protected void Arrange()
|
||||
{
|
||||
SetupData();
|
||||
CreateMocks();
|
||||
SetupMocks();
|
||||
|
||||
_client = new MyClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
_client.Connect();
|
||||
_client.KeepAliveInterval = _keepAliveInterval;
|
||||
}
|
||||
|
||||
protected void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
// allow keep-alive to be sent once
|
||||
Thread.Sleep(150);
|
||||
@@ -84,10 +69,16 @@ namespace Renci.SshNet.Tests.Classes
|
||||
Assert.AreEqual(TimeSpan.FromMilliseconds(-1), _client.KeepAliveInterval);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSocketFactoryOnServiceFactoryShouldBeInvokedOnce()
|
||||
{
|
||||
_serviceFactoryMock.Verify(p => p.CreateSocketFactory(), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSessionOnServiceFactoryShouldBeInvokedOnce()
|
||||
{
|
||||
_serviceFactoryMock.Verify(p => p.CreateSession(_connectionInfo), Times.Once);
|
||||
_serviceFactoryMock.Verify(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
+36
-45
@@ -7,24 +7,42 @@ using Renci.SshNet.Messages.Transport;
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class BaseClientTest_Connected_KeepAliveInterval_NotNegativeOne
|
||||
public class BaseClientTest_Connected_KeepAliveInterval_NotNegativeOne : BaseClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private BaseClient _client;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private TimeSpan _keepAliveInterval;
|
||||
private int _keepAliveCount;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
protected override void SetupData()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
_connectionInfo = new ConnectionInfo("host", "user", new PasswordAuthenticationMethod("user", "pwd"));
|
||||
_keepAliveInterval = TimeSpan.FromMilliseconds(50d);
|
||||
_keepAliveCount = 0;
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
_serviceFactoryMock.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.Setup(p => p.Connect());
|
||||
_sessionMock.Setup(p => p.IsConnected).Returns(true);
|
||||
_sessionMock.Setup(p => p.TrySendMessage(It.IsAny<IgnoreMessage>()))
|
||||
.Returns(true)
|
||||
.Callback(() => Interlocked.Increment(ref _keepAliveCount));
|
||||
}
|
||||
|
||||
protected override void Arrange()
|
||||
{
|
||||
base.Arrange();
|
||||
|
||||
_client = new MyClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
_client.Connect();
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
if (_client != null)
|
||||
{
|
||||
@@ -34,41 +52,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupData()
|
||||
{
|
||||
_connectionInfo = new ConnectionInfo("host", "user", new PasswordAuthenticationMethod("user", "pwd"));
|
||||
_keepAliveInterval = TimeSpan.FromMilliseconds(50d);
|
||||
_keepAliveCount = 0;
|
||||
}
|
||||
|
||||
private void CreateMocks()
|
||||
{
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
}
|
||||
|
||||
private void SetupMocks()
|
||||
{
|
||||
_serviceFactoryMock.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.Setup(p => p.Connect());
|
||||
_sessionMock.Setup(p => p.IsConnected).Returns(true);
|
||||
_sessionMock.Setup(p => p.TrySendMessage(It.IsAny<IgnoreMessage>()))
|
||||
.Returns(true)
|
||||
.Callback(() => Interlocked.Increment(ref _keepAliveCount));
|
||||
}
|
||||
|
||||
protected void Arrange()
|
||||
{
|
||||
SetupData();
|
||||
CreateMocks();
|
||||
SetupMocks();
|
||||
|
||||
_client = new MyClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
_client.Connect();
|
||||
}
|
||||
|
||||
protected void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
_client.KeepAliveInterval = _keepAliveInterval;
|
||||
|
||||
@@ -82,10 +66,17 @@ namespace Renci.SshNet.Tests.Classes
|
||||
Assert.AreEqual(_keepAliveInterval, _client.KeepAliveInterval);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSocketFactoryOnServiceFactoryShouldBeInvokedOnce()
|
||||
{
|
||||
_serviceFactoryMock.Verify(p => p.CreateSocketFactory(), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSessionOnServiceFactoryShouldBeInvokedOnce()
|
||||
{
|
||||
_serviceFactoryMock.Verify(p => p.CreateSession(_connectionInfo), Times.Once);
|
||||
_serviceFactoryMock.Verify(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
+39
-50
@@ -7,24 +7,53 @@ using Renci.SshNet.Messages.Transport;
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class BaseClientTest_Connected_KeepAlivesNotSentConcurrently
|
||||
public class BaseClientTest_Connected_KeepAlivesNotSentConcurrently : BaseClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private MockSequence _mockSequence;
|
||||
private BaseClient _client;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private ManualResetEvent _keepAliveSent;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
protected override void SetupData()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
_connectionInfo = new ConnectionInfo("host", "user", new PasswordAuthenticationMethod("user", "pwd"));
|
||||
_keepAliveSent = new ManualResetEvent(false);
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
_mockSequence = new MockSequence();
|
||||
|
||||
_serviceFactoryMock.InSequence(_mockSequence)
|
||||
.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.InSequence(_mockSequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(_mockSequence)
|
||||
.Setup(p => p.Connect());
|
||||
_sessionMock.InSequence(_mockSequence)
|
||||
.Setup(p => p.TrySendMessage(It.IsAny<IgnoreMessage>()))
|
||||
.Returns(true)
|
||||
.Callback(() =>
|
||||
{
|
||||
Thread.Sleep(300);
|
||||
_keepAliveSent.Set();
|
||||
});
|
||||
}
|
||||
|
||||
protected override void Arrange()
|
||||
{
|
||||
base.Arrange();
|
||||
|
||||
_client = new MyClient(_connectionInfo, false, _serviceFactoryMock.Object)
|
||||
{
|
||||
KeepAliveInterval = TimeSpan.FromMilliseconds(50d)
|
||||
};
|
||||
_client.Connect();
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
if (_client != null)
|
||||
{
|
||||
@@ -34,47 +63,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupData()
|
||||
{
|
||||
_connectionInfo = new ConnectionInfo("host", "user", new PasswordAuthenticationMethod("user", "pwd"));
|
||||
_keepAliveSent = new ManualResetEvent(false);
|
||||
}
|
||||
|
||||
private void CreateMocks()
|
||||
{
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
}
|
||||
|
||||
private void SetupMocks()
|
||||
{
|
||||
_mockSequence = new MockSequence();
|
||||
|
||||
_serviceFactoryMock.InSequence(_mockSequence).Setup(p => p.CreateSession(_connectionInfo)).Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(_mockSequence).Setup(p => p.Connect());
|
||||
_sessionMock.InSequence(_mockSequence).Setup(p => p.TrySendMessage(It.IsAny<IgnoreMessage>()))
|
||||
.Returns(true)
|
||||
.Callback(() =>
|
||||
{
|
||||
Thread.Sleep(300);
|
||||
_keepAliveSent.Set();
|
||||
});
|
||||
}
|
||||
|
||||
protected void Arrange()
|
||||
{
|
||||
SetupData();
|
||||
CreateMocks();
|
||||
SetupMocks();
|
||||
|
||||
_client = new MyClient(_connectionInfo, false, _serviceFactoryMock.Object)
|
||||
{
|
||||
KeepAliveInterval = TimeSpan.FromMilliseconds(50d)
|
||||
};
|
||||
_client.Connect();
|
||||
}
|
||||
|
||||
protected void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
// should keep-alive message be sent concurrently, then multiple keep-alive
|
||||
// message would be sent during this sleep period
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Connection;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class BaseClientTest_Disconnected_Connect : BaseClientTestBase
|
||||
{
|
||||
private Mock<ISocketFactory> _socketFactory2Mock;
|
||||
private Mock<ISession> _session2Mock;
|
||||
private BaseClient _client;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
_connectionInfo = new ConnectionInfo("host", "user", new PasswordAuthenticationMethod("user", "pwd"));
|
||||
}
|
||||
|
||||
protected override void CreateMocks()
|
||||
{
|
||||
base.CreateMocks();
|
||||
|
||||
_socketFactory2Mock = new Mock<ISocketFactory>(MockBehavior.Strict);
|
||||
_session2Mock = new Mock<ISession>(MockBehavior.Strict);
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
var sequence = new MockSequence();
|
||||
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence)
|
||||
.Setup(p => p.Connect());
|
||||
_sessionMock.InSequence(sequence)
|
||||
.Setup(p => p.OnDisconnecting());
|
||||
_sessionMock.InSequence(sequence)
|
||||
.Setup(p => p.Dispose());
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactory2Mock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo, _socketFactory2Mock.Object))
|
||||
.Returns(_session2Mock.Object);
|
||||
_session2Mock.InSequence(sequence)
|
||||
.Setup(p => p.Connect());
|
||||
}
|
||||
|
||||
protected override void Arrange()
|
||||
{
|
||||
base.Arrange();
|
||||
|
||||
_client = new MyClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
_client.Connect();
|
||||
_client.Disconnect();
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
if (_client != null)
|
||||
{
|
||||
_session2Mock.Setup(p => p.OnDisconnecting());
|
||||
_session2Mock.Setup(p => p.Dispose());
|
||||
_client.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
_client.Connect();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSocketFactoryOnServiceFactoryShouldBeInvokedTwic()
|
||||
{
|
||||
_serviceFactoryMock.Verify(p => p.CreateSocketFactory(), Times.Exactly(2));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSessionOnServiceFactoryShouldBeInvokedTwice()
|
||||
{
|
||||
_serviceFactoryMock.Verify(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object),
|
||||
Times.Once);
|
||||
_serviceFactoryMock.Verify(p => p.CreateSession(_connectionInfo, _socketFactory2Mock.Object),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectOnSessionShouldBeInvokedTwice()
|
||||
{
|
||||
_sessionMock.Verify(p => p.Connect(), Times.Once);
|
||||
_session2Mock.Verify(p => p.Connect(), Times.Once);
|
||||
}
|
||||
|
||||
private class MyClient : BaseClient
|
||||
{
|
||||
public MyClient(ConnectionInfo connectionInfo, bool ownsConnectionInfo, IServiceFactory serviceFactory) : base(connectionInfo, ownsConnectionInfo, serviceFactory)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+34
-43
@@ -7,23 +7,39 @@ using Renci.SshNet.Messages.Transport;
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class BaseClientTest_Disconnected_KeepAliveInterval_NotNegativeOne
|
||||
public class BaseClientTest_Disconnected_KeepAliveInterval_NotNegativeOne : BaseClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private BaseClient _client;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private TimeSpan _keepAliveInterval;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
protected override void SetupData()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
_connectionInfo = new ConnectionInfo("host", "user", new PasswordAuthenticationMethod("user", "pwd"));
|
||||
_keepAliveInterval = TimeSpan.FromMilliseconds(50d);
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
_serviceFactoryMock.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.Setup(p => p.Connect());
|
||||
_sessionMock.Setup(p => p.IsConnected).Returns(false);
|
||||
_sessionMock.Setup(p => p.TrySendMessage(It.IsAny<IgnoreMessage>()))
|
||||
.Returns(true);
|
||||
}
|
||||
|
||||
protected override void Arrange()
|
||||
{
|
||||
base.Arrange();
|
||||
|
||||
_client = new MyClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
_client.Connect();
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
if (_client != null)
|
||||
{
|
||||
@@ -33,39 +49,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupData()
|
||||
{
|
||||
_connectionInfo = new ConnectionInfo("host", "user", new PasswordAuthenticationMethod("user", "pwd"));
|
||||
_keepAliveInterval = TimeSpan.FromMilliseconds(50d);
|
||||
}
|
||||
|
||||
private void CreateMocks()
|
||||
{
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
}
|
||||
|
||||
private void SetupMocks()
|
||||
{
|
||||
_serviceFactoryMock.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.Setup(p => p.Connect());
|
||||
_sessionMock.Setup(p => p.IsConnected).Returns(false);
|
||||
_sessionMock.Setup(p => p.TrySendMessage(It.IsAny<IgnoreMessage>()))
|
||||
.Returns(true);
|
||||
}
|
||||
|
||||
protected void Arrange()
|
||||
{
|
||||
SetupData();
|
||||
CreateMocks();
|
||||
SetupMocks();
|
||||
|
||||
_client = new MyClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
_client.Connect();
|
||||
}
|
||||
|
||||
protected void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
_client.KeepAliveInterval = _keepAliveInterval;
|
||||
|
||||
@@ -79,10 +63,17 @@ namespace Renci.SshNet.Tests.Classes
|
||||
Assert.AreEqual(_keepAliveInterval, _client.KeepAliveInterval);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSocketFactoryOnServiceFactoryShouldBeInvokedOnce()
|
||||
{
|
||||
_serviceFactoryMock.Verify(p => p.CreateSocketFactory(), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSessionOnServiceFactoryShouldBeInvokedOnce()
|
||||
{
|
||||
_serviceFactoryMock.Verify(p => p.CreateSession(_connectionInfo), Times.Once);
|
||||
_serviceFactoryMock.Verify(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
+18
-37
@@ -7,24 +7,28 @@ using Renci.SshNet.Messages.Transport;
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class BaseClientTest_NotConnected_KeepAliveInterval_NotNegativeOne
|
||||
public class BaseClientTest_NotConnected_KeepAliveInterval_NotNegativeOne : BaseClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private BaseClient _client;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private TimeSpan _keepAliveInterval;
|
||||
private int _keepAliveCount;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
protected override void SetupData()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
_connectionInfo = new ConnectionInfo("host", "user", new PasswordAuthenticationMethod("user", "pwd"));
|
||||
_keepAliveInterval = TimeSpan.FromMilliseconds(100d);
|
||||
_keepAliveCount = 0;
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
protected override void Arrange()
|
||||
{
|
||||
base.Arrange();
|
||||
|
||||
_client = new MyClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
if (_client != null)
|
||||
{
|
||||
@@ -34,33 +38,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupData()
|
||||
{
|
||||
_connectionInfo = new ConnectionInfo("host", "user", new PasswordAuthenticationMethod("user", "pwd"));
|
||||
_keepAliveInterval = TimeSpan.FromMilliseconds(100d);
|
||||
_keepAliveCount = 0;
|
||||
}
|
||||
|
||||
private void CreateMocks()
|
||||
{
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
}
|
||||
|
||||
private static void SetupMocks()
|
||||
{
|
||||
}
|
||||
|
||||
protected void Arrange()
|
||||
{
|
||||
SetupData();
|
||||
CreateMocks();
|
||||
SetupMocks();
|
||||
|
||||
_client = new MyClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
}
|
||||
|
||||
protected void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
_client.KeepAliveInterval = _keepAliveInterval;
|
||||
|
||||
@@ -77,7 +55,10 @@ namespace Renci.SshNet.Tests.Classes
|
||||
[TestMethod]
|
||||
public void ConnectShouldActivateKeepAliveIfSessionIs()
|
||||
{
|
||||
_serviceFactoryMock.Setup(p => p.CreateSession(_connectionInfo)).Returns(_sessionMock.Object);
|
||||
_serviceFactoryMock.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.Setup(p => p.Connect());
|
||||
_sessionMock.Setup(p => p.TrySendMessage(It.IsAny<IgnoreMessage>()))
|
||||
.Returns(true)
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
using Moq;
|
||||
using Renci.SshNet.Connection;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using System.Net;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
public abstract class DirectConnectorTestBase : TripleATestBase
|
||||
{
|
||||
internal Mock<ISocketFactory> SocketFactoryMock { get; private set; }
|
||||
internal DirectConnector Connector { get; private set; }
|
||||
internal SocketFactory SocketFactory { get; private set; }
|
||||
|
||||
protected virtual void CreateMocks()
|
||||
{
|
||||
SocketFactoryMock = new Mock<ISocketFactory>(MockBehavior.Strict);
|
||||
}
|
||||
|
||||
protected virtual void SetupData()
|
||||
{
|
||||
Connector = new DirectConnector(SocketFactoryMock.Object);
|
||||
SocketFactory = new SocketFactory();
|
||||
}
|
||||
|
||||
protected virtual void SetupMocks()
|
||||
{
|
||||
}
|
||||
|
||||
protected sealed override void Arrange()
|
||||
{
|
||||
CreateMocks();
|
||||
SetupData();
|
||||
SetupMocks();
|
||||
}
|
||||
|
||||
protected ConnectionInfo CreateConnectionInfo(string hostName)
|
||||
{
|
||||
return new ConnectionInfo(hostName,
|
||||
777,
|
||||
"user",
|
||||
new KeyboardInteractiveAuthenticationMethod("user"));
|
||||
}
|
||||
}
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Common;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class DirectConnectorTest_Connect_ConnectionRefusedByServer : DirectConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private SocketException _actualException;
|
||||
private Socket _clientSocket;
|
||||
private Stopwatch _stopWatch;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
_connectionInfo = CreateConnectionInfo(IPAddress.Loopback.ToString());
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(5000);
|
||||
_stopWatch = new Stopwatch();
|
||||
_actualException = null;
|
||||
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_clientSocket != null)
|
||||
{
|
||||
_clientSocket.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
_stopWatch.Start();
|
||||
|
||||
try
|
||||
{
|
||||
Connector.Connect(_connectionInfo);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
_actualException = ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_stopWatch.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveThrownSocketException()
|
||||
{
|
||||
Assert.IsNull(_actualException.InnerException);
|
||||
Assert.AreEqual(SocketError.ConnectionRefused, _actualException.SocketErrorCode);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveRespectedTimeout()
|
||||
{
|
||||
var errorText = string.Format("Elapsed: {0}, Timeout: {1}",
|
||||
_stopWatch.ElapsedMilliseconds,
|
||||
_connectionInfo.Timeout.TotalMilliseconds);
|
||||
|
||||
Assert.IsTrue(_stopWatch.ElapsedMilliseconds < _connectionInfo.Timeout.TotalMilliseconds, errorText);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldHaveBeenDisposed()
|
||||
{
|
||||
try
|
||||
{
|
||||
_clientSocket.Receive(new byte[0]);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class DirectConnectorTest_Connect_ConnectionSucceeded : DirectConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private AsyncSocketListener _server;
|
||||
private Socket _clientSocket;
|
||||
private Stopwatch _stopWatch;
|
||||
private bool _disconnected;
|
||||
private Socket _actual;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
var random = new Random();
|
||||
|
||||
_connectionInfo = CreateConnectionInfo(IPAddress.Loopback.ToString());
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(random.Next(50, 200));
|
||||
_stopWatch = new Stopwatch();
|
||||
_disconnected = false;
|
||||
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
_server = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.Port));
|
||||
_server.Disconnected += (socket) => _disconnected = true;
|
||||
_server.Connected += (socket) => socket.Send(new byte[1] { 0x44 });
|
||||
_server.Start();
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_server != null)
|
||||
{
|
||||
_server.Dispose();
|
||||
}
|
||||
|
||||
if (_clientSocket != null)
|
||||
{
|
||||
_clientSocket.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
_stopWatch.Start();
|
||||
|
||||
try
|
||||
{
|
||||
_actual = Connector.Connect(_connectionInfo);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_stopWatch.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveReturnedSocketCreatedUsingSocketFactory()
|
||||
{
|
||||
Assert.IsNotNull(_actual);
|
||||
Assert.AreSame(_clientSocket, _actual);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveRespectedTimeout()
|
||||
{
|
||||
var errorText = string.Format("Elapsed: {0}, Timeout: {1}",
|
||||
_stopWatch.ElapsedMilliseconds,
|
||||
_connectionInfo.Timeout.TotalMilliseconds);
|
||||
|
||||
Assert.IsTrue(_stopWatch.ElapsedMilliseconds < (_connectionInfo.Timeout.TotalMilliseconds + 100), errorText);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldBeConnected()
|
||||
{
|
||||
Assert.IsTrue(_clientSocket.Connected);
|
||||
Assert.IsFalse(_disconnected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void NoBytesShouldHaveBeenReadFromSocket()
|
||||
{
|
||||
var buffer = new byte[1];
|
||||
|
||||
var bytesRead = _clientSocket.Receive(buffer);
|
||||
Assert.AreEqual(1, bytesRead);
|
||||
Assert.AreEqual(0x44, buffer[0]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class DirectConnectorTest_Connect_HostNameInvalid : DirectConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private SocketException _actualException;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
_connectionInfo = CreateConnectionInfo("invalid.");
|
||||
_actualException = null;
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
try
|
||||
{
|
||||
Connector.Connect(_connectionInfo);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
_actualException = ex;
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveThrownSocketException()
|
||||
{
|
||||
Assert.IsNotNull(_actualException);
|
||||
Assert.IsNull(_actualException.InnerException);
|
||||
Assert.AreEqual(SocketError.HostNotFound, _actualException.SocketErrorCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class DirectConnectorTest_Connect_TimeoutConnectingToServer : DirectConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private SshOperationTimeoutException _actualException;
|
||||
private Socket _clientSocket;
|
||||
private Stopwatch _stopWatch;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
var random = new Random();
|
||||
|
||||
_connectionInfo = CreateConnectionInfo(IPAddress.Loopback.ToString());
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(random.Next(50, 200));
|
||||
_stopWatch = new Stopwatch();
|
||||
_actualException = null;
|
||||
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_clientSocket != null)
|
||||
{
|
||||
_clientSocket.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
_stopWatch.Start();
|
||||
|
||||
try
|
||||
{
|
||||
Connector.Connect(_connectionInfo);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshOperationTimeoutException ex)
|
||||
{
|
||||
_actualException = ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_stopWatch.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveThrownSshOperationTimeoutException()
|
||||
{
|
||||
Assert.IsNull(_actualException.InnerException);
|
||||
Assert.AreEqual(string.Format(CultureInfo.InvariantCulture, "Connection failed to establish within {0} milliseconds.", _connectionInfo.Timeout.TotalMilliseconds), _actualException.Message);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveRespectedTimeout()
|
||||
{
|
||||
var errorText = string.Format("Elapsed: {0}, Timeout: {1}",
|
||||
_stopWatch.ElapsedMilliseconds,
|
||||
_connectionInfo.Timeout.TotalMilliseconds);
|
||||
|
||||
Assert.IsTrue(_stopWatch.ElapsedMilliseconds >= _connectionInfo.Timeout.TotalMilliseconds, errorText);
|
||||
Assert.IsTrue(_stopWatch.ElapsedMilliseconds < (_connectionInfo.Timeout.TotalMilliseconds + 100), errorText);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldHaveBeenDisposed()
|
||||
{
|
||||
try
|
||||
{
|
||||
_clientSocket.Receive(new byte[0]);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using Moq;
|
||||
using Renci.SshNet.Connection;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
public abstract class HttpConnectorTestBase : TripleATestBase
|
||||
{
|
||||
internal Mock<ISocketFactory> SocketFactoryMock { get; private set; }
|
||||
internal HttpConnector Connector { get; private set; }
|
||||
internal SocketFactory SocketFactory { get; private set; }
|
||||
|
||||
protected virtual void CreateMocks()
|
||||
{
|
||||
SocketFactoryMock = new Mock<ISocketFactory>(MockBehavior.Strict);
|
||||
}
|
||||
|
||||
protected virtual void SetupData()
|
||||
{
|
||||
Connector = new HttpConnector(SocketFactoryMock.Object);
|
||||
SocketFactory = new SocketFactory();
|
||||
}
|
||||
|
||||
protected virtual void SetupMocks()
|
||||
{
|
||||
}
|
||||
|
||||
protected sealed override void Arrange()
|
||||
{
|
||||
CreateMocks();
|
||||
SetupData();
|
||||
SetupMocks();
|
||||
}
|
||||
}
|
||||
}
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Common;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class HttpConnectorTest_Connect_ConnectionToProxyRefused : HttpConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private SocketException _actualException;
|
||||
private Socket _clientSocket;
|
||||
private Stopwatch _stopWatch;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
_connectionInfo = new ConnectionInfo(IPAddress.Loopback.ToString(),
|
||||
777,
|
||||
"user",
|
||||
ProxyTypes.Http,
|
||||
IPAddress.Loopback.ToString(),
|
||||
8122,
|
||||
"proxyUser",
|
||||
"proxyPwd",
|
||||
new KeyboardInteractiveAuthenticationMethod("user"));
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(5000);
|
||||
_stopWatch = new Stopwatch();
|
||||
_actualException = null;
|
||||
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_clientSocket != null)
|
||||
{
|
||||
_clientSocket.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
_stopWatch.Start();
|
||||
|
||||
try
|
||||
{
|
||||
Connector.Connect(_connectionInfo);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
_actualException = ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_stopWatch.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveThrownSocketException()
|
||||
{
|
||||
Assert.IsNull(_actualException.InnerException);
|
||||
Assert.AreEqual(SocketError.ConnectionRefused, _actualException.SocketErrorCode);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveRespectedTimeout()
|
||||
{
|
||||
var errorText = string.Format("Elapsed: {0}, Timeout: {1}",
|
||||
_stopWatch.ElapsedMilliseconds,
|
||||
_connectionInfo.Timeout.TotalMilliseconds);
|
||||
|
||||
Assert.IsTrue(_stopWatch.ElapsedMilliseconds < _connectionInfo.Timeout.TotalMilliseconds, errorText);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldHaveBeenDisposed()
|
||||
{
|
||||
try
|
||||
{
|
||||
_clientSocket.Receive(new byte[0]);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class HttpConnectorTest_Connect_ProxyClosesConnectionBeforeStatusLineIsSent : HttpConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private AsyncSocketListener _proxyServer;
|
||||
private Socket _clientSocket;
|
||||
private bool _disconnected;
|
||||
private ProxyException _actualException;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
_connectionInfo = new ConnectionInfo(IPAddress.Loopback.ToString(),
|
||||
777,
|
||||
"user",
|
||||
ProxyTypes.Http,
|
||||
IPAddress.Loopback.ToString(),
|
||||
8122,
|
||||
"proxyUser",
|
||||
"proxyPwd",
|
||||
new KeyboardInteractiveAuthenticationMethod("user"));
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(100);
|
||||
_actualException = null;
|
||||
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
_proxyServer = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.ProxyPort));
|
||||
_proxyServer.Disconnected += socket => _disconnected = true;
|
||||
_proxyServer.BytesReceived += (bytesReceived, socket) =>
|
||||
{
|
||||
socket.Shutdown(SocketShutdown.Send);
|
||||
};
|
||||
_proxyServer.Start();
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_proxyServer != null)
|
||||
{
|
||||
_proxyServer.Dispose();
|
||||
}
|
||||
|
||||
if (_clientSocket != null)
|
||||
{
|
||||
_clientSocket.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
try
|
||||
{
|
||||
Connector.Connect(_connectionInfo);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ProxyException ex)
|
||||
{
|
||||
_actualException = ex;
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveThrownProxyException()
|
||||
{
|
||||
Assert.IsNotNull(_actualException);
|
||||
Assert.IsNull(_actualException.InnerException);
|
||||
Assert.AreEqual("HTTP response does not contain status line.", _actualException.Message);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectionToProxyShouldHaveBeenShutDown()
|
||||
{
|
||||
Assert.IsTrue(_disconnected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldHaveBeenDisposed()
|
||||
{
|
||||
try
|
||||
{
|
||||
_clientSocket.Receive(new byte[0]);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class HttpConnectorTest_Connect_ProxyHostInvalid : HttpConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private SocketException _actualException;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
_connectionInfo = new ConnectionInfo("localhost",
|
||||
40,
|
||||
"user",
|
||||
ProxyTypes.Http,
|
||||
"invalid.",
|
||||
80,
|
||||
"proxyUser",
|
||||
"proxyPwd",
|
||||
new KeyboardInteractiveAuthenticationMethod("user"));
|
||||
_actualException = null;
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
try
|
||||
{
|
||||
Connector.Connect(_connectionInfo);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
_actualException = ex;
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveThrownSocketException()
|
||||
{
|
||||
Assert.IsNotNull(_actualException);
|
||||
Assert.IsNull(_actualException.InnerException);
|
||||
Assert.AreEqual(SocketError.HostNotFound, _actualException.SocketErrorCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class HttpConnectorTest_Connect_ProxyPasswordIsEmpty : HttpConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private AsyncSocketListener _proxyServer;
|
||||
private bool _disconnected;
|
||||
private Socket _clientSocket;
|
||||
private List<byte> _bytesReceivedByProxy;
|
||||
private string _expectedHttpRequest;
|
||||
private Socket _actual;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
_connectionInfo = new ConnectionInfo(IPAddress.Loopback.ToString(),
|
||||
777,
|
||||
"user",
|
||||
ProxyTypes.Http,
|
||||
IPAddress.Loopback.ToString(),
|
||||
8122,
|
||||
"proxyUser",
|
||||
string.Empty,
|
||||
new KeyboardInteractiveAuthenticationMethod("user"));
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(20);
|
||||
_expectedHttpRequest = string.Format("CONNECT {0}:{1} HTTP/1.0{2}" +
|
||||
"Proxy-Authorization: Basic cHJveHlVc2VyOg=={2}{2}",
|
||||
_connectionInfo.Host,
|
||||
_connectionInfo.Port.ToString(CultureInfo.InvariantCulture),
|
||||
"\r\n");
|
||||
_bytesReceivedByProxy = new List<byte>();
|
||||
_disconnected = false;
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
_proxyServer = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.ProxyPort));
|
||||
_proxyServer.Disconnected += (socket) => _disconnected = true;
|
||||
_proxyServer.Connected += socket =>
|
||||
{
|
||||
socket.Send(Encoding.ASCII.GetBytes("\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("SSH.NET\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("HTTP/1.0 200 OK\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("Content-Type: application/octet-stream\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("SSH4EVER"));
|
||||
socket.Shutdown(SocketShutdown.Send);
|
||||
};
|
||||
_proxyServer.BytesReceived += (bytesReceived, socket) =>
|
||||
{
|
||||
_bytesReceivedByProxy.AddRange(bytesReceived);
|
||||
};
|
||||
_proxyServer.Start();
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_proxyServer != null)
|
||||
{
|
||||
_proxyServer.Dispose();
|
||||
}
|
||||
|
||||
if (_clientSocket != null)
|
||||
{
|
||||
_clientSocket.Shutdown(SocketShutdown.Both);
|
||||
_clientSocket.Close();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
_actual = Connector.Connect(_connectionInfo);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ProxyShouldHaveReceivedExpectedHttpRequest()
|
||||
{
|
||||
Assert.AreEqual(_expectedHttpRequest, Encoding.ASCII.GetString(_bytesReceivedByProxy.ToArray()));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldReturnSocketCreatedUsingSocketFactory()
|
||||
{
|
||||
Assert.IsNotNull(_actual);
|
||||
Assert.AreSame(_clientSocket, _actual);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void OnlyHttpResponseShouldHaveBeenConsumed()
|
||||
{
|
||||
var buffer = new byte[8];
|
||||
|
||||
Assert.AreEqual(8, _actual.Available);
|
||||
Assert.AreEqual(8, _actual.Receive(buffer));
|
||||
Assert.AreEqual("SSH4EVER", Encoding.ASCII.GetString(buffer));
|
||||
Assert.AreEqual(0, _actual.Receive(buffer));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldBeConnected()
|
||||
{
|
||||
Assert.IsFalse(_disconnected);
|
||||
Assert.IsTrue(_actual.Connected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class HttpConnectorTest_Connect_ProxyPasswordIsNull : HttpConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private AsyncSocketListener _proxyServer;
|
||||
private bool _disconnected;
|
||||
private Socket _clientSocket;
|
||||
private List<byte> _bytesReceivedByProxy;
|
||||
private string _expectedHttpRequest;
|
||||
private Socket _actual;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
_connectionInfo = new ConnectionInfo(IPAddress.Loopback.ToString(),
|
||||
777,
|
||||
"user",
|
||||
ProxyTypes.Http,
|
||||
IPAddress.Loopback.ToString(),
|
||||
8122,
|
||||
"proxyUser",
|
||||
null,
|
||||
new KeyboardInteractiveAuthenticationMethod("user"));
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(20);
|
||||
_expectedHttpRequest = string.Format("CONNECT {0}:{1} HTTP/1.0{2}" +
|
||||
"Proxy-Authorization: Basic cHJveHlVc2VyOg=={2}{2}",
|
||||
_connectionInfo.Host,
|
||||
_connectionInfo.Port.ToString(CultureInfo.InvariantCulture),
|
||||
"\r\n");
|
||||
_bytesReceivedByProxy = new List<byte>();
|
||||
_disconnected = false;
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
_proxyServer = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.ProxyPort));
|
||||
_proxyServer.Disconnected += (socket) => _disconnected = true;
|
||||
_proxyServer.Connected += socket =>
|
||||
{
|
||||
socket.Send(Encoding.ASCII.GetBytes("\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("SSH.NET\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("HTTP/1.0 200 OK\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("Content-Type: application/octet-stream\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("SSH4EVER"));
|
||||
socket.Shutdown(SocketShutdown.Send);
|
||||
};
|
||||
_proxyServer.BytesReceived += (bytesReceived, socket) =>
|
||||
{
|
||||
_bytesReceivedByProxy.AddRange(bytesReceived);
|
||||
};
|
||||
_proxyServer.Start();
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_proxyServer != null)
|
||||
{
|
||||
_proxyServer.Dispose();
|
||||
}
|
||||
|
||||
if (_clientSocket != null)
|
||||
{
|
||||
_clientSocket.Shutdown(SocketShutdown.Both);
|
||||
_clientSocket.Close();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
_actual = Connector.Connect(_connectionInfo);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ProxyShouldHaveReceivedExpectedHttpRequest()
|
||||
{
|
||||
Assert.AreEqual(_expectedHttpRequest, Encoding.ASCII.GetString(_bytesReceivedByProxy.ToArray()));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldReturnSocketCreatedUsingSocketFactory()
|
||||
{
|
||||
Assert.IsNotNull(_actual);
|
||||
Assert.AreSame(_clientSocket, _actual);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void OnlyHttpResponseShouldHaveBeenConsumed()
|
||||
{
|
||||
var buffer = new byte[8];
|
||||
|
||||
Assert.AreEqual(8, _actual.Available);
|
||||
Assert.AreEqual(8, _actual.Receive(buffer));
|
||||
Assert.AreEqual("SSH4EVER", Encoding.ASCII.GetString(buffer));
|
||||
Assert.AreEqual(0, _actual.Receive(buffer));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldBeConnected()
|
||||
{
|
||||
Assert.IsFalse(_disconnected);
|
||||
Assert.IsTrue(_actual.Connected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class HttpConnectorTest_Connect_ProxyResponseDoesNotContainHttpStatusLine : HttpConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private AsyncSocketListener _proxyServer;
|
||||
private Socket _clientSocket;
|
||||
private List<byte> _bytesReceivedByProxy;
|
||||
private bool _disconnected;
|
||||
private ProxyException _actualException;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
_connectionInfo = new ConnectionInfo(IPAddress.Loopback.ToString(),
|
||||
777,
|
||||
"user",
|
||||
ProxyTypes.Http,
|
||||
IPAddress.Loopback.ToString(),
|
||||
8122,
|
||||
"proxyUser",
|
||||
"proxyPwd",
|
||||
new KeyboardInteractiveAuthenticationMethod("user"));
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(100);
|
||||
_bytesReceivedByProxy = new List<byte>();
|
||||
_actualException = null;
|
||||
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
_proxyServer = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.ProxyPort));
|
||||
_proxyServer.Disconnected += socket => _disconnected = true;
|
||||
_proxyServer.BytesReceived += (bytesReceived, socket) =>
|
||||
{
|
||||
if (_bytesReceivedByProxy.Count == 0)
|
||||
{
|
||||
socket.Send(Encoding.ASCII.GetBytes("Whatever\r\n"));
|
||||
socket.Shutdown(SocketShutdown.Send);
|
||||
}
|
||||
|
||||
_bytesReceivedByProxy.AddRange(bytesReceived);
|
||||
};
|
||||
_proxyServer.Start();
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_proxyServer != null)
|
||||
{
|
||||
_proxyServer.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
try
|
||||
{
|
||||
Connector.Connect(_connectionInfo);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ProxyException ex)
|
||||
{
|
||||
_actualException = ex;
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveThrownProxyException()
|
||||
{
|
||||
Assert.IsNotNull(_actualException);
|
||||
Assert.IsNull(_actualException.InnerException);
|
||||
Assert.AreEqual("HTTP response does not contain status line.", _actualException.Message);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectionToProxyShouldHaveBeenShutDown()
|
||||
{
|
||||
Assert.IsTrue(_disconnected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldHaveBeenDisposed()
|
||||
{
|
||||
try
|
||||
{
|
||||
_clientSocket.Receive(new byte[0]);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class HttpConnectorTest_Connect_ProxyResponseStatusIs200_ExtraTextBeforeStatusLine : HttpConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private AsyncSocketListener _proxyServer;
|
||||
private bool _disconnected;
|
||||
private Socket _clientSocket;
|
||||
private List<byte> _bytesReceivedByProxy;
|
||||
private string _expectedHttpRequest;
|
||||
private Socket _actual;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
_connectionInfo = new ConnectionInfo(IPAddress.Loopback.ToString(),
|
||||
777,
|
||||
"user",
|
||||
ProxyTypes.Http,
|
||||
IPAddress.Loopback.ToString(),
|
||||
8122,
|
||||
"proxyUser",
|
||||
"proxyPwd",
|
||||
new KeyboardInteractiveAuthenticationMethod("user"));
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(20);
|
||||
_expectedHttpRequest = string.Format("CONNECT {0}:{1} HTTP/1.0{2}" +
|
||||
"Proxy-Authorization: Basic cHJveHlVc2VyOnByb3h5UHdk{2}{2}",
|
||||
_connectionInfo.Host,
|
||||
_connectionInfo.Port.ToString(CultureInfo.InvariantCulture),
|
||||
"\r\n");
|
||||
_bytesReceivedByProxy = new List<byte>();
|
||||
_disconnected = false;
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
_proxyServer = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.ProxyPort));
|
||||
_proxyServer.Disconnected += (socket) => _disconnected = true;
|
||||
_proxyServer.BytesReceived += (bytesReceived, socket) =>
|
||||
{
|
||||
_bytesReceivedByProxy.AddRange(bytesReceived);
|
||||
|
||||
// Only send response back after we've received the complete CONNECT request
|
||||
// as we want to make sure HttpConnector is not waiting for any data before
|
||||
// it sends the CONNECT request
|
||||
if (_bytesReceivedByProxy.Count == _expectedHttpRequest.Length)
|
||||
{
|
||||
socket.Send(Encoding.ASCII.GetBytes("\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("SSH.NET\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("HTTP/1.0 200 OK\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("Content-Type: application/octet-stream\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("SSH4EVER"));
|
||||
socket.Shutdown(SocketShutdown.Send);
|
||||
}
|
||||
};
|
||||
_proxyServer.Start();
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_proxyServer != null)
|
||||
{
|
||||
_proxyServer.Dispose();
|
||||
}
|
||||
|
||||
if (_clientSocket != null)
|
||||
{
|
||||
_clientSocket.Shutdown(SocketShutdown.Both);
|
||||
_clientSocket.Close();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
_actual = Connector.Connect(_connectionInfo);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ProxyShouldHaveReceivedExpectedHttpRequest()
|
||||
{
|
||||
Assert.AreEqual(_expectedHttpRequest, Encoding.ASCII.GetString(_bytesReceivedByProxy.ToArray()));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldReturnSocketCreatedUsingSocketFactory()
|
||||
{
|
||||
Assert.IsNotNull(_actual);
|
||||
Assert.AreSame(_clientSocket, _actual);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void OnlyHttpResponseShouldHaveBeenConsumed()
|
||||
{
|
||||
var buffer = new byte[8];
|
||||
|
||||
Assert.AreEqual(8, _actual.Available);
|
||||
Assert.AreEqual(8, _actual.Receive(buffer));
|
||||
Assert.AreEqual("SSH4EVER", Encoding.ASCII.GetString(buffer));
|
||||
Assert.AreEqual(0, _actual.Receive(buffer));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldBeConnected()
|
||||
{
|
||||
Assert.IsFalse(_disconnected);
|
||||
Assert.IsTrue(_actual.Connected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class HttpConnectorTest_Connect_ProxyResponseStatusIs200_HeadersAndContent : HttpConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private AsyncSocketListener _proxyServer;
|
||||
private bool _disconnected;
|
||||
private Socket _clientSocket;
|
||||
private List<byte> _bytesReceivedByProxy;
|
||||
private string _expectedHttpRequest;
|
||||
private Socket _actual;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
_connectionInfo = new ConnectionInfo(IPAddress.Loopback.ToString(),
|
||||
777,
|
||||
"user",
|
||||
ProxyTypes.Http,
|
||||
IPAddress.Loopback.ToString(),
|
||||
8122,
|
||||
"proxyUser",
|
||||
"proxyPwd",
|
||||
new KeyboardInteractiveAuthenticationMethod("user"));
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(20);
|
||||
_expectedHttpRequest = string.Format("CONNECT {0}:{1} HTTP/1.0{2}" +
|
||||
"Proxy-Authorization: Basic cHJveHlVc2VyOnByb3h5UHdk{2}{2}",
|
||||
_connectionInfo.Host,
|
||||
_connectionInfo.Port.ToString(CultureInfo.InvariantCulture),
|
||||
"\r\n");
|
||||
_bytesReceivedByProxy = new List<byte>();
|
||||
_disconnected = false;
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
_proxyServer = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.ProxyPort));
|
||||
_proxyServer.Disconnected += (socket) => _disconnected = true;
|
||||
_proxyServer.BytesReceived += (bytesReceived, socket) =>
|
||||
{
|
||||
_bytesReceivedByProxy.AddRange(bytesReceived);
|
||||
|
||||
// Only send response back after we've received the complete CONNECT request
|
||||
// as we want to make sure HttpConnector is not waiting for any data before
|
||||
// it sends the CONNECT request
|
||||
if (_bytesReceivedByProxy.Count == _expectedHttpRequest.Length)
|
||||
{
|
||||
socket.Send(Encoding.ASCII.GetBytes("HTTP/1.0 200 OK\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("Content-Length: 10\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("Content-Type: application/octet-stream\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("TEEN_BYTES"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("!666!"));
|
||||
socket.Shutdown(SocketShutdown.Send);
|
||||
}
|
||||
};
|
||||
_proxyServer.Start();
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_proxyServer != null)
|
||||
{
|
||||
_proxyServer.Dispose();
|
||||
}
|
||||
|
||||
if (_clientSocket != null)
|
||||
{
|
||||
_clientSocket.Shutdown(SocketShutdown.Both);
|
||||
_clientSocket.Close();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
_actual = Connector.Connect(_connectionInfo);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ProxyShouldHaveReceivedExpectedHttpRequest()
|
||||
{
|
||||
Assert.AreEqual(_expectedHttpRequest, Encoding.ASCII.GetString(_bytesReceivedByProxy.ToArray()));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldReturnSocketCreatedUsingSocketFactory()
|
||||
{
|
||||
Assert.IsNotNull(_actual);
|
||||
Assert.AreSame(_clientSocket, _actual);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void OnlyHttpResponseShouldHaveBeenConsumed()
|
||||
{
|
||||
var buffer = new byte[5];
|
||||
|
||||
Assert.AreEqual(5, _actual.Available);
|
||||
Assert.AreEqual(5, _actual.Receive(buffer));
|
||||
Assert.AreEqual("!666!", Encoding.ASCII.GetString(buffer));
|
||||
Assert.AreEqual(0, _actual.Receive(buffer));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldBeConnected()
|
||||
{
|
||||
Assert.IsFalse(_disconnected);
|
||||
Assert.IsTrue(_actual.Connected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class HttpConnectorTest_Connect_ProxyResponseStatusIs200_OnlyHeaders : HttpConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private AsyncSocketListener _proxyServer;
|
||||
private bool _disconnected;
|
||||
private Socket _clientSocket;
|
||||
private List<byte> _bytesReceivedByProxy;
|
||||
private string _expectedHttpRequest;
|
||||
private Socket _actual;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
_connectionInfo = new ConnectionInfo(IPAddress.Loopback.ToString(),
|
||||
777,
|
||||
"user",
|
||||
ProxyTypes.Http,
|
||||
IPAddress.Loopback.ToString(),
|
||||
8122,
|
||||
"proxyUser",
|
||||
"proxyPwd",
|
||||
new KeyboardInteractiveAuthenticationMethod("user"));
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(20);
|
||||
_expectedHttpRequest = string.Format("CONNECT {0}:{1} HTTP/1.0{2}" +
|
||||
"Proxy-Authorization: Basic cHJveHlVc2VyOnByb3h5UHdk{2}{2}",
|
||||
_connectionInfo.Host,
|
||||
_connectionInfo.Port.ToString(CultureInfo.InvariantCulture),
|
||||
"\r\n");
|
||||
_bytesReceivedByProxy = new List<byte>();
|
||||
_disconnected = false;
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
_proxyServer = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.ProxyPort));
|
||||
_proxyServer.Disconnected += (socket) => _disconnected = true;
|
||||
_proxyServer.BytesReceived += (bytesReceived, socket) =>
|
||||
{
|
||||
_bytesReceivedByProxy.AddRange(bytesReceived);
|
||||
|
||||
// Only send response back after we've received the complete CONNECT request
|
||||
// as we want to make sure HttpConnector is not waiting for any data before
|
||||
// it sends the CONNECT request
|
||||
if (_bytesReceivedByProxy.Count == _expectedHttpRequest.Length)
|
||||
{
|
||||
socket.Send(Encoding.ASCII.GetBytes("HTTP/1.0 200 OK\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("Content-Type: application/octet-stream\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("SSH4EVER"));
|
||||
socket.Shutdown(SocketShutdown.Send);
|
||||
}
|
||||
};
|
||||
_proxyServer.Start();
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_proxyServer != null)
|
||||
{
|
||||
_proxyServer.Dispose();
|
||||
}
|
||||
|
||||
if (_clientSocket != null)
|
||||
{
|
||||
_clientSocket.Shutdown(SocketShutdown.Both);
|
||||
_clientSocket.Close();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
_actual = Connector.Connect(_connectionInfo);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ProxyShouldHaveReceivedExpectedHttpRequest()
|
||||
{
|
||||
Assert.AreEqual(_expectedHttpRequest, Encoding.ASCII.GetString(_bytesReceivedByProxy.ToArray()));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldReturnSocketCreatedUsingSocketFactory()
|
||||
{
|
||||
Assert.IsNotNull(_actual);
|
||||
Assert.AreSame(_clientSocket, _actual);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void OnlyHttpResponseShouldHaveBeenConsumed()
|
||||
{
|
||||
var buffer = new byte[8];
|
||||
|
||||
Assert.AreEqual(8, _actual.Available);
|
||||
Assert.AreEqual(8, _actual.Receive(buffer));
|
||||
Assert.AreEqual("SSH4EVER", Encoding.ASCII.GetString(buffer));
|
||||
Assert.AreEqual(0, _actual.Receive(buffer));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldBeConnected()
|
||||
{
|
||||
Assert.IsFalse(_disconnected);
|
||||
Assert.IsTrue(_actual.Connected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class HttpConnectorTest_Connect_ProxyResponseStatusIsNot200 : HttpConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private AsyncSocketListener _proxyServer;
|
||||
private Socket _clientSocket;
|
||||
private List<byte> _bytesReceivedByProxy;
|
||||
private bool _disconnected;
|
||||
private ProxyException _actualException;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
_connectionInfo = new ConnectionInfo(IPAddress.Loopback.ToString(),
|
||||
777,
|
||||
"user",
|
||||
ProxyTypes.Http,
|
||||
IPAddress.Loopback.ToString(),
|
||||
8122,
|
||||
"proxyUser",
|
||||
"proxyPwd",
|
||||
new KeyboardInteractiveAuthenticationMethod("user"));
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(100);
|
||||
_bytesReceivedByProxy = new List<byte>();
|
||||
_actualException = null;
|
||||
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
_proxyServer = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.ProxyPort));
|
||||
_proxyServer.Disconnected += (socket) => _disconnected = true;
|
||||
_proxyServer.BytesReceived += (bytesReceived, socket) =>
|
||||
{
|
||||
if (_bytesReceivedByProxy.Count == 0)
|
||||
{
|
||||
socket.Send(Encoding.ASCII.GetBytes("HTTP/1.0 404 I searched everywhere, really...\r\n"));
|
||||
socket.Shutdown(SocketShutdown.Send);
|
||||
}
|
||||
|
||||
_bytesReceivedByProxy.AddRange(bytesReceived);
|
||||
};
|
||||
_proxyServer.Start();
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_proxyServer != null)
|
||||
{
|
||||
_proxyServer.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
try
|
||||
{
|
||||
Connector.Connect(_connectionInfo);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ProxyException ex)
|
||||
{
|
||||
_actualException = ex;
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveThrownProxyException()
|
||||
{
|
||||
Assert.IsNotNull(_actualException);
|
||||
Assert.IsNull(_actualException.InnerException);
|
||||
Assert.AreEqual("HTTP: Status code 404, \"I searched everywhere, really...\"", _actualException.Message);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectionToProxyShouldHaveBeenShutDown()
|
||||
{
|
||||
Assert.IsTrue(_disconnected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldHaveBeenDisposed()
|
||||
{
|
||||
try
|
||||
{
|
||||
_clientSocket.Receive(new byte[0]);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class HttpConnectorTest_Connect_ProxyUserNameIsEmpty : HttpConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private AsyncSocketListener _proxyServer;
|
||||
private bool _disconnected;
|
||||
private Socket _clientSocket;
|
||||
private List<byte> _bytesReceivedByProxy;
|
||||
private string _expectedHttpRequest;
|
||||
private Socket _actual;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
_connectionInfo = new ConnectionInfo(IPAddress.Loopback.ToString(),
|
||||
777,
|
||||
"user",
|
||||
ProxyTypes.Http,
|
||||
IPAddress.Loopback.ToString(),
|
||||
8122,
|
||||
string.Empty,
|
||||
"proxyPwd",
|
||||
new KeyboardInteractiveAuthenticationMethod("user"));
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(20);
|
||||
_expectedHttpRequest = string.Format("CONNECT {0}:{1} HTTP/1.0{2}{2}",
|
||||
_connectionInfo.Host,
|
||||
_connectionInfo.Port.ToString(CultureInfo.InvariantCulture),
|
||||
"\r\n");
|
||||
_bytesReceivedByProxy = new List<byte>();
|
||||
_disconnected = false;
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
_proxyServer = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.ProxyPort));
|
||||
_proxyServer.Disconnected += (socket) => _disconnected = true;
|
||||
_proxyServer.BytesReceived += (bytesReceived, socket) =>
|
||||
{
|
||||
_bytesReceivedByProxy.AddRange(bytesReceived);
|
||||
|
||||
// Only send response back after we've received the complete CONNECT request
|
||||
// as we want to make sure HttpConnector is not waiting for any data before
|
||||
// it sends the CONNECT request
|
||||
if (_bytesReceivedByProxy.Count == _expectedHttpRequest.Length)
|
||||
{
|
||||
socket.Send(Encoding.ASCII.GetBytes("\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("SSH.NET\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("HTTP/1.0 200 OK\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("Content-Type: application/octet-stream\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("SSH4EVER"));
|
||||
}
|
||||
};
|
||||
_proxyServer.Start();
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_clientSocket != null)
|
||||
{
|
||||
_clientSocket.Shutdown(SocketShutdown.Send);
|
||||
_clientSocket.Close();
|
||||
}
|
||||
|
||||
if (_proxyServer != null)
|
||||
{
|
||||
_proxyServer.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
_actual = Connector.Connect(_connectionInfo);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ProxyShouldHaveReceivedExpectedHttpRequest()
|
||||
{
|
||||
Assert.AreEqual(_expectedHttpRequest, Encoding.ASCII.GetString(_bytesReceivedByProxy.ToArray()));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldReturnSocketCreatedUsingSocketFactory()
|
||||
{
|
||||
Assert.IsNotNull(_actual);
|
||||
Assert.AreSame(_clientSocket, _actual);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void OnlyHttpResponseShouldHaveBeenConsumed()
|
||||
{
|
||||
var buffer = new byte[8];
|
||||
|
||||
Assert.AreEqual(8, _actual.Available);
|
||||
Assert.AreEqual(8, _actual.Receive(buffer));
|
||||
Assert.AreEqual("SSH4EVER", Encoding.ASCII.GetString(buffer));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldBeConnected()
|
||||
{
|
||||
Assert.IsFalse(_disconnected);
|
||||
Assert.IsTrue(_actual.Connected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class HttpConnectorTest_Connect_ProxyUserNameIsNotNullAndNotEmpty : HttpConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private AsyncSocketListener _proxyServer;
|
||||
private bool _disconnected;
|
||||
private Socket _clientSocket;
|
||||
private List<byte> _bytesReceivedByProxy;
|
||||
private string _expectedHttpRequest;
|
||||
private Socket _actual;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
_connectionInfo = new ConnectionInfo(IPAddress.Loopback.ToString(),
|
||||
777,
|
||||
"user",
|
||||
ProxyTypes.Http,
|
||||
IPAddress.Loopback.ToString(),
|
||||
8122,
|
||||
"user",
|
||||
"pwd",
|
||||
new KeyboardInteractiveAuthenticationMethod("user"));
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(20);
|
||||
_expectedHttpRequest = string.Format("CONNECT {0}:{1} HTTP/1.0{2}" +
|
||||
"Proxy-Authorization: Basic dXNlcjpwd2Q={2}{2}",
|
||||
_connectionInfo.Host,
|
||||
_connectionInfo.Port.ToString(CultureInfo.InvariantCulture),
|
||||
"\r\n");
|
||||
_bytesReceivedByProxy = new List<byte>();
|
||||
_disconnected = false;
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
_proxyServer = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.ProxyPort));
|
||||
_proxyServer.Connected += (socket) =>
|
||||
{
|
||||
socket.Send(Encoding.ASCII.GetBytes("HTTP/1.0 200 OK\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("Content-Type: application/octet-stream\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("SSH4EVER"));
|
||||
};
|
||||
_proxyServer.Disconnected += (socket) => _disconnected = true;
|
||||
_proxyServer.BytesReceived += (bytesReceived, socket) =>
|
||||
{
|
||||
_bytesReceivedByProxy.AddRange(bytesReceived);
|
||||
};
|
||||
_proxyServer.Start();
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_proxyServer != null)
|
||||
{
|
||||
_proxyServer.Dispose();
|
||||
}
|
||||
|
||||
if (_clientSocket != null)
|
||||
{
|
||||
_clientSocket.Shutdown(SocketShutdown.Both);
|
||||
_clientSocket.Close();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
_actual = Connector.Connect(_connectionInfo);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ProxyShouldHaveReceivedExpectedHttpRequest()
|
||||
{
|
||||
Assert.AreEqual(_expectedHttpRequest, Encoding.ASCII.GetString(_bytesReceivedByProxy.ToArray()));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldReturnSocketCreatedUsingSocketFactory()
|
||||
{
|
||||
Assert.IsNotNull(_actual);
|
||||
Assert.AreSame(_clientSocket, _actual);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void OnlyHttpResponseShouldHaveBeenConsumed()
|
||||
{
|
||||
var buffer = new byte[8];
|
||||
|
||||
Assert.AreEqual(8, _actual.Available);
|
||||
Assert.AreEqual(8, _actual.Receive(buffer));
|
||||
Assert.AreEqual("SSH4EVER", Encoding.ASCII.GetString(buffer));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldBeConnected()
|
||||
{
|
||||
Assert.IsFalse(_disconnected);
|
||||
Assert.IsTrue(_actual.Connected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class HttpConnectorTest_Connect_ProxyUserNameIsNull : HttpConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private AsyncSocketListener _proxyServer;
|
||||
private bool _disconnected;
|
||||
private Socket _clientSocket;
|
||||
private List<byte> _bytesReceivedByProxy;
|
||||
private string _expectedHttpRequest;
|
||||
private Socket _actual;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
_connectionInfo = new ConnectionInfo(IPAddress.Loopback.ToString(),
|
||||
777,
|
||||
"user",
|
||||
ProxyTypes.Http,
|
||||
IPAddress.Loopback.ToString(),
|
||||
8122,
|
||||
null,
|
||||
"proxyPwd",
|
||||
new KeyboardInteractiveAuthenticationMethod("user"));
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(20);
|
||||
_expectedHttpRequest = string.Format("CONNECT {0}:{1} HTTP/1.0{2}{2}",
|
||||
_connectionInfo.Host,
|
||||
_connectionInfo.Port.ToString(CultureInfo.InvariantCulture),
|
||||
"\r\n");
|
||||
_bytesReceivedByProxy = new List<byte>();
|
||||
_disconnected = false;
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
_proxyServer = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.ProxyPort));
|
||||
_proxyServer.Disconnected += (socket) => _disconnected = true;
|
||||
_proxyServer.BytesReceived += (bytesReceived, socket) =>
|
||||
{
|
||||
_bytesReceivedByProxy.AddRange(bytesReceived);
|
||||
|
||||
// Only send response back after we've received the complete CONNECT request
|
||||
// as we want to make sure HttpConnector is not waiting for any data before
|
||||
// it sends the CONNECT request
|
||||
if (_bytesReceivedByProxy.Count == _expectedHttpRequest.Length)
|
||||
{
|
||||
socket.Send(Encoding.ASCII.GetBytes("\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("SSH.NET\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("HTTP/1.0 200 OK\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("Content-Type: application/octet-stream\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("SSH4EVER"));
|
||||
}
|
||||
};
|
||||
_proxyServer.Start();
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_clientSocket != null)
|
||||
{
|
||||
_clientSocket.Shutdown(SocketShutdown.Send);
|
||||
_clientSocket.Close();
|
||||
}
|
||||
|
||||
if (_proxyServer != null)
|
||||
{
|
||||
_proxyServer.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
_actual = Connector.Connect(_connectionInfo);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ProxyShouldHaveReceivedExpectedHttpRequest()
|
||||
{
|
||||
Assert.AreEqual(_expectedHttpRequest, Encoding.ASCII.GetString(_bytesReceivedByProxy.ToArray()));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldReturnSocketCreatedUsingSocketFactory()
|
||||
{
|
||||
Assert.IsNotNull(_actual);
|
||||
Assert.AreSame(_clientSocket, _actual);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void OnlyHttpResponseShouldHaveBeenConsumed()
|
||||
{
|
||||
var buffer = new byte[8];
|
||||
|
||||
Assert.AreEqual(8, _actual.Available);
|
||||
Assert.AreEqual(8, _actual.Receive(buffer));
|
||||
Assert.AreEqual("SSH4EVER", Encoding.ASCII.GetString(buffer));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldBeConnected()
|
||||
{
|
||||
Assert.IsFalse(_disconnected);
|
||||
Assert.IsTrue(_actual.Connected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Common;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class HttpConnectorTest_Connect_TimeoutConnectingToProxy : HttpConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private SshOperationTimeoutException _actualException;
|
||||
private Socket _clientSocket;
|
||||
private Stopwatch _stopWatch;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
var random = new Random();
|
||||
|
||||
_connectionInfo = new ConnectionInfo(IPAddress.Loopback.ToString(),
|
||||
777,
|
||||
"user",
|
||||
ProxyTypes.Http,
|
||||
IPAddress.Loopback.ToString(),
|
||||
8122,
|
||||
"proxyUser",
|
||||
"proxyPwd",
|
||||
new KeyboardInteractiveAuthenticationMethod("user"));
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(random.Next(50, 200));
|
||||
_stopWatch = new Stopwatch();
|
||||
_actualException = null;
|
||||
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_clientSocket != null)
|
||||
{
|
||||
_clientSocket.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
_stopWatch.Start();
|
||||
|
||||
try
|
||||
{
|
||||
Connector.Connect(_connectionInfo);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshOperationTimeoutException ex)
|
||||
{
|
||||
_actualException = ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_stopWatch.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveThrownSshOperationTimeoutException()
|
||||
{
|
||||
Assert.IsNull(_actualException.InnerException);
|
||||
Assert.AreEqual(string.Format(CultureInfo.InvariantCulture, "Connection failed to establish within {0} milliseconds.", _connectionInfo.Timeout.TotalMilliseconds), _actualException.Message);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveRespectedTimeout()
|
||||
{
|
||||
var errorText = string.Format("Elapsed: {0}, Timeout: {1}",
|
||||
_stopWatch.ElapsedMilliseconds,
|
||||
_connectionInfo.Timeout.TotalMilliseconds);
|
||||
|
||||
Assert.IsTrue(_stopWatch.ElapsedMilliseconds >= _connectionInfo.Timeout.TotalMilliseconds, errorText);
|
||||
Assert.IsTrue(_stopWatch.ElapsedMilliseconds < (_connectionInfo.Timeout.TotalMilliseconds + 100), errorText);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldHaveBeenDisposed()
|
||||
{
|
||||
try
|
||||
{
|
||||
_clientSocket.Receive(new byte[0]);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
+169
@@ -0,0 +1,169 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Connection;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class HttpConnectorTest_Connect_TimeoutReadingHttpContent : HttpConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private SshOperationTimeoutException _actualException;
|
||||
private Socket _clientSocket;
|
||||
private AsyncSocketListener _proxyServer;
|
||||
private List<byte> _bytesReceivedByProxy;
|
||||
private string _expectedHttpRequest;
|
||||
private Stopwatch _stopWatch;
|
||||
private AsyncSocketListener _server;
|
||||
private bool _disconnected;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
var random = new Random();
|
||||
|
||||
_connectionInfo = new ConnectionInfo(IPAddress.Loopback.ToString(),
|
||||
777,
|
||||
"user",
|
||||
ProxyTypes.Http,
|
||||
IPAddress.Loopback.ToString(),
|
||||
8122,
|
||||
"proxyUser",
|
||||
"proxyPwd",
|
||||
new KeyboardInteractiveAuthenticationMethod("user"));
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(random.Next(50, 200));
|
||||
_expectedHttpRequest = string.Format("CONNECT {0}:{1} HTTP/1.0{2}" +
|
||||
"Proxy-Authorization: Basic cHJveHlVc2VyOnByb3h5UHdk{2}{2}",
|
||||
_connectionInfo.Host,
|
||||
_connectionInfo.Port.ToString(CultureInfo.InvariantCulture),
|
||||
"\r\n");
|
||||
_bytesReceivedByProxy = new List<byte>();
|
||||
_stopWatch = new Stopwatch();
|
||||
_actualException = null;
|
||||
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
_proxyServer = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.ProxyPort));
|
||||
_proxyServer.Disconnected += (socket) => _disconnected = true;
|
||||
_proxyServer.BytesReceived += (bytesReceived, socket) =>
|
||||
{
|
||||
_bytesReceivedByProxy.AddRange(bytesReceived);
|
||||
|
||||
// Force a timeout by sending less content than indicated by Content-Length header
|
||||
if (_bytesReceivedByProxy.Count == _expectedHttpRequest.Length)
|
||||
{
|
||||
socket.Send(Encoding.ASCII.GetBytes("HTTP/1.0 200 OK\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("Content-Length: 10\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("Content-Type: application/octet-stream\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("TOO_FEW"));
|
||||
}
|
||||
};
|
||||
_proxyServer.Start();
|
||||
|
||||
_server = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.Port));
|
||||
_server.Start();
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_server != null)
|
||||
{
|
||||
_server.Dispose();
|
||||
}
|
||||
|
||||
if (_proxyServer != null)
|
||||
{
|
||||
_proxyServer.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
_stopWatch.Start();
|
||||
|
||||
try
|
||||
{
|
||||
Connector.Connect(_connectionInfo);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshOperationTimeoutException ex)
|
||||
{
|
||||
_actualException = ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_stopWatch.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveThrownSshOperationTimeoutException()
|
||||
{
|
||||
Assert.IsNull(_actualException.InnerException);
|
||||
Assert.AreEqual(string.Format(CultureInfo.InvariantCulture, "Socket read operation has timed out after {0:F0} milliseconds.", _connectionInfo.Timeout.TotalMilliseconds), _actualException.Message);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ProxyShouldHaveReceivedExpectedHttpRequest()
|
||||
{
|
||||
Assert.AreEqual(_expectedHttpRequest, Encoding.ASCII.GetString(_bytesReceivedByProxy.ToArray()));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveRespectedTimeout()
|
||||
{
|
||||
var errorText = string.Format("Elapsed: {0}, Timeout: {1}",
|
||||
_stopWatch.ElapsedMilliseconds,
|
||||
_connectionInfo.Timeout.TotalMilliseconds);
|
||||
|
||||
Assert.IsTrue(_stopWatch.ElapsedMilliseconds >= _connectionInfo.Timeout.TotalMilliseconds, errorText);
|
||||
Assert.IsTrue(_stopWatch.ElapsedMilliseconds < (_connectionInfo.Timeout.TotalMilliseconds + 100), errorText);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldNotBeConnected()
|
||||
{
|
||||
Assert.IsTrue(_disconnected);
|
||||
Assert.IsFalse(_clientSocket.Connected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldHaveBeenDisposed()
|
||||
{
|
||||
try
|
||||
{
|
||||
_clientSocket.Receive(new byte[0]);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Connection;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class HttpConnectorTest_Connect_TimeoutReadingStatusLine : HttpConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private SshOperationTimeoutException _actualException;
|
||||
private Socket _clientSocket;
|
||||
private AsyncSocketListener _proxyServer;
|
||||
private Stopwatch _stopWatch;
|
||||
private AsyncSocketListener _server;
|
||||
private bool _disconnected;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
var random = new Random();
|
||||
|
||||
_connectionInfo = new ConnectionInfo(IPAddress.Loopback.ToString(),
|
||||
777,
|
||||
"user",
|
||||
ProxyTypes.Http,
|
||||
IPAddress.Loopback.ToString(),
|
||||
8122,
|
||||
"proxyUser",
|
||||
"proxyPwd",
|
||||
new KeyboardInteractiveAuthenticationMethod("user"));
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(random.Next(50, 200));
|
||||
_stopWatch = new Stopwatch();
|
||||
_actualException = null;
|
||||
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
_proxyServer = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.ProxyPort));
|
||||
_proxyServer.Disconnected += (socket) => _disconnected = true;
|
||||
_proxyServer.Start();
|
||||
|
||||
_server = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.Port));
|
||||
_server.Start();
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_server != null)
|
||||
{
|
||||
_server.Dispose();
|
||||
}
|
||||
|
||||
if (_proxyServer != null)
|
||||
{
|
||||
_proxyServer.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
_stopWatch.Start();
|
||||
|
||||
try
|
||||
{
|
||||
Connector.Connect(_connectionInfo);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshOperationTimeoutException ex)
|
||||
{
|
||||
_actualException = ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_stopWatch.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveThrownSshOperationTimeoutException()
|
||||
{
|
||||
Assert.IsNull(_actualException.InnerException);
|
||||
Assert.AreEqual(string.Format(CultureInfo.InvariantCulture, "Socket read operation has timed out after {0:F0} milliseconds.", _connectionInfo.Timeout.TotalMilliseconds), _actualException.Message);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveRespectedTimeout()
|
||||
{
|
||||
var errorText = string.Format("Elapsed: {0}, Timeout: {1}",
|
||||
_stopWatch.ElapsedMilliseconds,
|
||||
_connectionInfo.Timeout.TotalMilliseconds);
|
||||
|
||||
Assert.IsTrue(_stopWatch.ElapsedMilliseconds >= _connectionInfo.Timeout.TotalMilliseconds, errorText);
|
||||
Assert.IsTrue(_stopWatch.ElapsedMilliseconds < (_connectionInfo.Timeout.TotalMilliseconds + 100), errorText);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldNotBeConnected()
|
||||
{
|
||||
Assert.IsTrue(_disconnected);
|
||||
Assert.IsFalse(_clientSocket.Connected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldHaveBeenDisposed()
|
||||
{
|
||||
try
|
||||
{
|
||||
_clientSocket.Receive(new byte[0]);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
-6
@@ -55,16 +55,16 @@ namespace Renci.SshNet.Tests.Classes
|
||||
_timeout = TimeSpan.FromSeconds(5);
|
||||
_serverEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
|
||||
_dataReceivedByServer = new List<byte>();
|
||||
_serverIdentification = Encoding.UTF8.GetBytes("Welcome stranger!\r\n\r\nSSH-ABC2.0-OurSSHAppliance-1.4.7 Use at own risk.\uD55C\r\n!");
|
||||
_serverIdentification = Encoding.UTF8.GetBytes("\r\nWelcome stranger!\r\n\r\nSSH-ABC2.0-OurSSHAppliance-1.4.7 Use at own risk.\uD55C\r\n!");
|
||||
|
||||
_server = new AsyncSocketListener(_serverEndPoint);
|
||||
_server.Start();
|
||||
_server.BytesReceived += (bytes, socket) =>
|
||||
{
|
||||
_dataReceivedByServer.AddRange(bytes);
|
||||
socket.Send(_serverIdentification);
|
||||
socket.Shutdown(SocketShutdown.Both);
|
||||
};
|
||||
{
|
||||
_dataReceivedByServer.AddRange(bytes);
|
||||
socket.Send(_serverIdentification);
|
||||
socket.Shutdown(SocketShutdown.Both);
|
||||
};
|
||||
_server.Disconnected += (socket) => _clientDisconnected = true;
|
||||
|
||||
_client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
using Moq;
|
||||
using Renci.SshNet.Connection;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using System.Net;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
public abstract class Socks4ConnectorTestBase : TripleATestBase
|
||||
{
|
||||
internal Mock<ISocketFactory> SocketFactoryMock { get; private set; }
|
||||
internal Socks4Connector Connector { get; private set; }
|
||||
internal SocketFactory SocketFactory { get; private set; }
|
||||
|
||||
protected virtual void CreateMocks()
|
||||
{
|
||||
SocketFactoryMock = new Mock<ISocketFactory>(MockBehavior.Strict);
|
||||
}
|
||||
|
||||
protected virtual void SetupData()
|
||||
{
|
||||
Connector = new Socks4Connector(SocketFactoryMock.Object);
|
||||
SocketFactory = new SocketFactory();
|
||||
}
|
||||
|
||||
protected virtual void SetupMocks()
|
||||
{
|
||||
}
|
||||
|
||||
protected sealed override void Arrange()
|
||||
{
|
||||
CreateMocks();
|
||||
SetupData();
|
||||
SetupMocks();
|
||||
}
|
||||
|
||||
protected ConnectionInfo CreateConnectionInfo(string proxyUser, string proxyPassword)
|
||||
{
|
||||
return new ConnectionInfo(IPAddress.Loopback.ToString(),
|
||||
777,
|
||||
"user",
|
||||
ProxyTypes.Socks4,
|
||||
IPAddress.Loopback.ToString(),
|
||||
8122,
|
||||
proxyUser,
|
||||
proxyPassword,
|
||||
new KeyboardInteractiveAuthenticationMethod("user"));
|
||||
}
|
||||
}
|
||||
}
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class Socks4ConnectorTest_Connect_ConnectionRejectedByProxy : Socks4ConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private AsyncSocketListener _proxyServer;
|
||||
private Socket _clientSocket;
|
||||
private List<byte> _bytesReceivedByProxy;
|
||||
private bool _disconnected;
|
||||
private ProxyException _actualException;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
_connectionInfo = CreateConnectionInfo("proxyUser", "proxyPwd");
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(100);
|
||||
_bytesReceivedByProxy = new List<byte>();
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
_actualException = null;
|
||||
|
||||
_proxyServer = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.ProxyPort));
|
||||
_proxyServer.Disconnected += socket => _disconnected = true;
|
||||
_proxyServer.BytesReceived += (bytesReceived, socket) =>
|
||||
{
|
||||
if (_bytesReceivedByProxy.Count == 0)
|
||||
{
|
||||
socket.Send(new byte[]
|
||||
{
|
||||
// Reply version (null byte)
|
||||
0x00,
|
||||
// Connection refused
|
||||
0x5b
|
||||
});
|
||||
}
|
||||
|
||||
_bytesReceivedByProxy.AddRange(bytesReceived);
|
||||
};
|
||||
_proxyServer.Start();
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_proxyServer != null)
|
||||
{
|
||||
_proxyServer.Dispose();
|
||||
}
|
||||
|
||||
if (_clientSocket != null)
|
||||
{
|
||||
_clientSocket.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
try
|
||||
{
|
||||
Connector.Connect(_connectionInfo);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ProxyException ex)
|
||||
{
|
||||
_actualException = ex;
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveThrownProxyException()
|
||||
{
|
||||
Assert.IsNotNull(_actualException);
|
||||
Assert.IsNull(_actualException.InnerException);
|
||||
Assert.AreEqual("SOCKS4: Connection rejected.", _actualException.Message);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectionToProxyShouldHaveBeenShutDown()
|
||||
{
|
||||
Assert.IsTrue(_disconnected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldHaveBeenDisposed()
|
||||
{
|
||||
try
|
||||
{
|
||||
_clientSocket.Receive(new byte[0]);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
|
||||
private static byte GetNotSupportedSocksVersion()
|
||||
{
|
||||
var random = new Random();
|
||||
|
||||
while (true)
|
||||
{
|
||||
var socksVersion = random.Next(1, 255);
|
||||
if (socksVersion != 4)
|
||||
{
|
||||
return (byte) socksVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+166
@@ -0,0 +1,166 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Connection;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class Socks4ConnectorTest_Connect_ConnectionSucceeded : Socks4ConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private Socket _clientSocket;
|
||||
private AsyncSocketListener _proxyServer;
|
||||
private List<byte> _bytesReceivedByProxy;
|
||||
private bool _disconnected;
|
||||
private Socket _actual;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
var random = new Random();
|
||||
|
||||
_connectionInfo = CreateConnectionInfo("proxyUser", "proxyPwd");
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(random.Next(50, 200));
|
||||
_bytesReceivedByProxy = new List<byte>();
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
_actual = null;
|
||||
|
||||
_proxyServer = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.ProxyPort));
|
||||
_proxyServer.Disconnected += socket => _disconnected = true;
|
||||
_proxyServer.BytesReceived += (bytesReceived, socket) =>
|
||||
{
|
||||
_bytesReceivedByProxy.AddRange(bytesReceived);
|
||||
|
||||
if (_bytesReceivedByProxy.Count == bytesReceived.Length)
|
||||
{
|
||||
// Send SOCKS response
|
||||
socket.Send(new byte[]
|
||||
{
|
||||
// Reply version (null byte)
|
||||
0x00,
|
||||
// Request granted
|
||||
0x5a,
|
||||
// Destination address port
|
||||
0x01,
|
||||
0xf0,
|
||||
// Destination address IP
|
||||
0x01,
|
||||
0x02,
|
||||
0x03,
|
||||
0x04
|
||||
});
|
||||
|
||||
// Send extra byte to allow us to verify that connector did not consume too much
|
||||
socket.Send(new byte[]
|
||||
{
|
||||
0xfe
|
||||
});
|
||||
}
|
||||
};
|
||||
_proxyServer.Start();
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_proxyServer != null)
|
||||
{
|
||||
_proxyServer.Dispose();
|
||||
}
|
||||
|
||||
if (_clientSocket != null)
|
||||
{
|
||||
_clientSocket.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
_actual = Connector.Connect(_connectionInfo);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ProxyShouldHaveReceivedExpectedSocksRequest()
|
||||
{
|
||||
var expectedSocksRequest = new byte[]
|
||||
{
|
||||
// SOCKS version
|
||||
0x04,
|
||||
// CONNECT request
|
||||
0x01,
|
||||
// Destination port
|
||||
0x03,
|
||||
0x09,
|
||||
// Destination address (IPv4)
|
||||
0x7f,
|
||||
0x00,
|
||||
0x00,
|
||||
0x01,
|
||||
// Proxy user
|
||||
0x70,
|
||||
0x72,
|
||||
0x6f,
|
||||
0x78,
|
||||
0x79,
|
||||
0x55,
|
||||
0x73,
|
||||
0x65,
|
||||
0x72,
|
||||
// Null terminator
|
||||
0x00
|
||||
};
|
||||
|
||||
var errorText = string.Format("Expected:{0}{1}{0}but was:{0}{2}",
|
||||
Environment.NewLine,
|
||||
PacketDump.Create(expectedSocksRequest, 2),
|
||||
PacketDump.Create(_bytesReceivedByProxy, 2));
|
||||
|
||||
Assert.IsTrue(expectedSocksRequest.SequenceEqual(_bytesReceivedByProxy), errorText);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldReturnSocketCreatedUsingSocketFactory()
|
||||
{
|
||||
Assert.IsNotNull(_actual);
|
||||
Assert.AreSame(_clientSocket, _actual);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void OnlySocksResponseShouldHaveBeenConsumed()
|
||||
{
|
||||
var buffer = new byte[2];
|
||||
|
||||
Assert.AreEqual(1, _actual.Receive(buffer));
|
||||
Assert.AreEqual(0xfe, buffer[0]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldBeConnected()
|
||||
{
|
||||
Assert.IsFalse(_disconnected);
|
||||
Assert.IsTrue(_actual.Connected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Common;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class Socks4ConnectorTest_Connect_ConnectionToProxyRefused : Socks4ConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private SocketException _actualException;
|
||||
private Socket _clientSocket;
|
||||
private Stopwatch _stopWatch;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
_connectionInfo = CreateConnectionInfo("proxyUser", "proxyPwd");
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(5000);
|
||||
_stopWatch = new Stopwatch();
|
||||
_actualException = null;
|
||||
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_clientSocket != null)
|
||||
{
|
||||
_clientSocket.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
_stopWatch.Start();
|
||||
|
||||
try
|
||||
{
|
||||
Connector.Connect(_connectionInfo);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
_actualException = ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_stopWatch.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveThrownSocketException()
|
||||
{
|
||||
Assert.IsNull(_actualException.InnerException);
|
||||
Assert.AreEqual(SocketError.ConnectionRefused, _actualException.SocketErrorCode);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveRespectedTimeout()
|
||||
{
|
||||
var errorText = string.Format("Elapsed: {0}, Timeout: {1}",
|
||||
_stopWatch.ElapsedMilliseconds,
|
||||
_connectionInfo.Timeout.TotalMilliseconds);
|
||||
|
||||
Assert.IsTrue(_stopWatch.ElapsedMilliseconds < _connectionInfo.Timeout.TotalMilliseconds, errorText);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldHaveBeenDisposed()
|
||||
{
|
||||
try
|
||||
{
|
||||
_clientSocket.Receive(new byte[0]);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Common;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class Socks4ConnectorTest_Connect_TimeoutConnectingToProxy : Socks4ConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private SshOperationTimeoutException _actualException;
|
||||
private Socket _clientSocket;
|
||||
private Stopwatch _stopWatch;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
var random = new Random();
|
||||
|
||||
_connectionInfo = CreateConnectionInfo("proxyUser", "proxyPwd");
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(random.Next(50, 200));
|
||||
_stopWatch = new Stopwatch();
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
_actualException = null;
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_clientSocket != null)
|
||||
{
|
||||
_clientSocket.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
_stopWatch.Start();
|
||||
|
||||
try
|
||||
{
|
||||
Connector.Connect(_connectionInfo);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshOperationTimeoutException ex)
|
||||
{
|
||||
_actualException = ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_stopWatch.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveThrownSshOperationTimeoutException()
|
||||
{
|
||||
Assert.IsNull(_actualException.InnerException);
|
||||
Assert.AreEqual(string.Format(CultureInfo.InvariantCulture, "Connection failed to establish within {0} milliseconds.", _connectionInfo.Timeout.TotalMilliseconds), _actualException.Message);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveRespectedTimeout()
|
||||
{
|
||||
var errorText = string.Format("Elapsed: {0}, Timeout: {1}",
|
||||
_stopWatch.ElapsedMilliseconds,
|
||||
_connectionInfo.Timeout.TotalMilliseconds);
|
||||
|
||||
Assert.IsTrue(_stopWatch.ElapsedMilliseconds >= _connectionInfo.Timeout.TotalMilliseconds, errorText);
|
||||
Assert.IsTrue(_stopWatch.ElapsedMilliseconds < (_connectionInfo.Timeout.TotalMilliseconds + 100), errorText);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldHaveBeenDisposed()
|
||||
{
|
||||
try
|
||||
{
|
||||
_clientSocket.Receive(new byte[0]);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Connection;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class Socks4ConnectorTest_Connect_TimeoutReadingDestinationAddress : Socks4ConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private SshOperationTimeoutException _actualException;
|
||||
private Socket _clientSocket;
|
||||
private AsyncSocketListener _proxyServer;
|
||||
private Stopwatch _stopWatch;
|
||||
private AsyncSocketListener _server;
|
||||
private bool _disconnected;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
var random = new Random();
|
||||
|
||||
_connectionInfo = CreateConnectionInfo("proxyUser", "proxyPwd");
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(random.Next(50, 200));
|
||||
_stopWatch = new Stopwatch();
|
||||
_actualException = null;
|
||||
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
_proxyServer = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.ProxyPort));
|
||||
_proxyServer.Disconnected += socket => _disconnected = true;
|
||||
_proxyServer.Connected += socket =>
|
||||
{
|
||||
socket.Send(new byte[]
|
||||
{
|
||||
// Reply version (null byte)
|
||||
0x00,
|
||||
// Request granted
|
||||
0x5a,
|
||||
// Incomplete destination address
|
||||
0x01
|
||||
});
|
||||
};
|
||||
_proxyServer.Start();
|
||||
|
||||
_server = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.Port));
|
||||
_server.Start();
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_server != null)
|
||||
{
|
||||
_server.Dispose();
|
||||
}
|
||||
|
||||
if (_proxyServer != null)
|
||||
{
|
||||
_proxyServer.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
_stopWatch.Start();
|
||||
|
||||
try
|
||||
{
|
||||
Connector.Connect(_connectionInfo);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshOperationTimeoutException ex)
|
||||
{
|
||||
_actualException = ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_stopWatch.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveThrownSshOperationTimeoutException()
|
||||
{
|
||||
Assert.IsNull(_actualException.InnerException);
|
||||
Assert.AreEqual(string.Format(CultureInfo.InvariantCulture, "Socket read operation has timed out after {0:F0} milliseconds.", _connectionInfo.Timeout.TotalMilliseconds), _actualException.Message);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveRespectedTimeout()
|
||||
{
|
||||
var errorText = string.Format("Elapsed: {0}, Timeout: {1}",
|
||||
_stopWatch.ElapsedMilliseconds,
|
||||
_connectionInfo.Timeout.TotalMilliseconds);
|
||||
|
||||
Assert.IsTrue(_stopWatch.ElapsedMilliseconds >= _connectionInfo.Timeout.TotalMilliseconds, errorText);
|
||||
Assert.IsTrue(_stopWatch.ElapsedMilliseconds < (_connectionInfo.Timeout.TotalMilliseconds + 100), errorText);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldNotBeConnected()
|
||||
{
|
||||
Assert.IsTrue(_disconnected);
|
||||
Assert.IsFalse(_clientSocket.Connected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldHaveBeenDisposed()
|
||||
{
|
||||
try
|
||||
{
|
||||
_clientSocket.Receive(new byte[0]);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Connection;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class Socks4ConnectorTest_Connect_TimeoutReadingReplyCode : Socks4ConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private SshOperationTimeoutException _actualException;
|
||||
private Socket _clientSocket;
|
||||
private AsyncSocketListener _proxyServer;
|
||||
private Stopwatch _stopWatch;
|
||||
private AsyncSocketListener _server;
|
||||
private bool _disconnected;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
var random = new Random();
|
||||
|
||||
_connectionInfo = CreateConnectionInfo("proxyUser", "proxyPwd");
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(random.Next(50, 200));
|
||||
_stopWatch = new Stopwatch();
|
||||
_actualException = null;
|
||||
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
_proxyServer = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.ProxyPort));
|
||||
_proxyServer.Disconnected += socket => _disconnected = true;
|
||||
_proxyServer.Connected += socket =>
|
||||
{
|
||||
socket.Send(new byte[]
|
||||
{
|
||||
// Reply version (null byte)
|
||||
0x00
|
||||
});
|
||||
};
|
||||
_proxyServer.Start();
|
||||
|
||||
_server = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.Port));
|
||||
_server.Start();
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_server != null)
|
||||
{
|
||||
_server.Dispose();
|
||||
}
|
||||
|
||||
if (_proxyServer != null)
|
||||
{
|
||||
_proxyServer.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
_stopWatch.Start();
|
||||
|
||||
try
|
||||
{
|
||||
Connector.Connect(_connectionInfo);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshOperationTimeoutException ex)
|
||||
{
|
||||
_actualException = ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_stopWatch.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveThrownSshOperationTimeoutException()
|
||||
{
|
||||
Assert.IsNull(_actualException.InnerException);
|
||||
Assert.AreEqual(string.Format(CultureInfo.InvariantCulture, "Socket read operation has timed out after {0:F0} milliseconds.", _connectionInfo.Timeout.TotalMilliseconds), _actualException.Message);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveRespectedTimeout()
|
||||
{
|
||||
var errorText = string.Format("Elapsed: {0}, Timeout: {1}",
|
||||
_stopWatch.ElapsedMilliseconds,
|
||||
_connectionInfo.Timeout.TotalMilliseconds);
|
||||
|
||||
Assert.IsTrue(_stopWatch.ElapsedMilliseconds >= _connectionInfo.Timeout.TotalMilliseconds, errorText);
|
||||
Assert.IsTrue(_stopWatch.ElapsedMilliseconds < (_connectionInfo.Timeout.TotalMilliseconds + 100), errorText);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldNotBeConnected()
|
||||
{
|
||||
Assert.IsTrue(_disconnected);
|
||||
Assert.IsFalse(_clientSocket.Connected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldHaveBeenDisposed()
|
||||
{
|
||||
try
|
||||
{
|
||||
_clientSocket.Receive(new byte[0]);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Connection;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class Socks4ConnectorTest_Connect_TimeoutReadingReplyVersion : Socks4ConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private SshOperationTimeoutException _actualException;
|
||||
private Socket _clientSocket;
|
||||
private AsyncSocketListener _proxyServer;
|
||||
private Stopwatch _stopWatch;
|
||||
private AsyncSocketListener _server;
|
||||
private bool _disconnected;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
var random = new Random();
|
||||
|
||||
_connectionInfo = CreateConnectionInfo("proxyUser", "proxyPwd");
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(random.Next(50, 200));
|
||||
_stopWatch = new Stopwatch();
|
||||
_actualException = null;
|
||||
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
_proxyServer = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.ProxyPort));
|
||||
_proxyServer.Disconnected += socket => _disconnected = true;
|
||||
_proxyServer.Start();
|
||||
|
||||
_server = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.Port));
|
||||
_server.Start();
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_server != null)
|
||||
{
|
||||
_server.Dispose();
|
||||
}
|
||||
|
||||
if (_proxyServer != null)
|
||||
{
|
||||
_proxyServer.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
_stopWatch.Start();
|
||||
|
||||
try
|
||||
{
|
||||
Connector.Connect(_connectionInfo);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshOperationTimeoutException ex)
|
||||
{
|
||||
_actualException = ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_stopWatch.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveThrownSshOperationTimeoutException()
|
||||
{
|
||||
Assert.IsNull(_actualException.InnerException);
|
||||
Assert.AreEqual(string.Format(CultureInfo.InvariantCulture, "Socket read operation has timed out after {0:F0} milliseconds.", _connectionInfo.Timeout.TotalMilliseconds), _actualException.Message);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveRespectedTimeout()
|
||||
{
|
||||
var errorText = string.Format("Elapsed: {0}, Timeout: {1}",
|
||||
_stopWatch.ElapsedMilliseconds,
|
||||
_connectionInfo.Timeout.TotalMilliseconds);
|
||||
|
||||
Assert.IsTrue(_stopWatch.ElapsedMilliseconds >= _connectionInfo.Timeout.TotalMilliseconds, errorText);
|
||||
Assert.IsTrue(_stopWatch.ElapsedMilliseconds < (_connectionInfo.Timeout.TotalMilliseconds + 100), errorText);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldNotBeConnected()
|
||||
{
|
||||
Assert.IsTrue(_disconnected);
|
||||
Assert.IsFalse(_clientSocket.Connected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldHaveBeenDisposed()
|
||||
{
|
||||
try
|
||||
{
|
||||
_clientSocket.Receive(new byte[0]);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
using Moq;
|
||||
using Renci.SshNet.Connection;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
public abstract class Socks5ConnectorTestBase : TripleATestBase
|
||||
{
|
||||
internal Mock<ISocketFactory> SocketFactoryMock { get; private set; }
|
||||
internal Socks5Connector Connector { get; private set; }
|
||||
internal SocketFactory SocketFactory { get; private set; }
|
||||
|
||||
protected virtual void CreateMocks()
|
||||
{
|
||||
SocketFactoryMock = new Mock<ISocketFactory>(MockBehavior.Strict);
|
||||
}
|
||||
|
||||
protected virtual void SetupData()
|
||||
{
|
||||
Connector = new Socks5Connector(SocketFactoryMock.Object);
|
||||
SocketFactory = new SocketFactory();
|
||||
}
|
||||
|
||||
protected virtual void SetupMocks()
|
||||
{
|
||||
}
|
||||
|
||||
protected sealed override void Arrange()
|
||||
{
|
||||
CreateMocks();
|
||||
SetupData();
|
||||
SetupMocks();
|
||||
}
|
||||
|
||||
protected ConnectionInfo CreateConnectionInfo(string proxyUser, string proxyPassword)
|
||||
{
|
||||
return new ConnectionInfo(IPAddress.Loopback.ToString(),
|
||||
777,
|
||||
"user",
|
||||
ProxyTypes.Socks5,
|
||||
IPAddress.Loopback.ToString(),
|
||||
8122,
|
||||
proxyUser,
|
||||
proxyPassword,
|
||||
new KeyboardInteractiveAuthenticationMethod("user"));
|
||||
}
|
||||
|
||||
protected static string GenerateRandomString(int minLength, int maxLength)
|
||||
{
|
||||
var random = new Random();
|
||||
var length = random.Next(minLength, maxLength);
|
||||
|
||||
var sb = new StringBuilder(length);
|
||||
int offset = 'a';
|
||||
|
||||
for (var i = 0; i < length; i++)
|
||||
{
|
||||
var @char = (char) random.Next(offset, offset + 26);
|
||||
sb.Append(@char);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Common;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class Socks5ConnectorTest_Connect_ConnectionToProxyRefused : Socks5ConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private SocketException _actualException;
|
||||
private Socket _clientSocket;
|
||||
private Stopwatch _stopWatch;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
_connectionInfo = CreateConnectionInfo("proxyUser", "proxyPwd");
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(5000);
|
||||
_stopWatch = new Stopwatch();
|
||||
_actualException = null;
|
||||
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_clientSocket != null)
|
||||
{
|
||||
_clientSocket.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
_stopWatch.Start();
|
||||
|
||||
try
|
||||
{
|
||||
Connector.Connect(_connectionInfo);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
_actualException = ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_stopWatch.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveThrownSocketException()
|
||||
{
|
||||
Assert.IsNull(_actualException.InnerException);
|
||||
Assert.AreEqual(SocketError.ConnectionRefused, _actualException.SocketErrorCode);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveRespectedTimeout()
|
||||
{
|
||||
var errorText = string.Format("Elapsed: {0}, Timeout: {1}",
|
||||
_stopWatch.ElapsedMilliseconds,
|
||||
_connectionInfo.Timeout.TotalMilliseconds);
|
||||
|
||||
Assert.IsTrue(_stopWatch.ElapsedMilliseconds < _connectionInfo.Timeout.TotalMilliseconds, errorText);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldHaveBeenDisposed()
|
||||
{
|
||||
try
|
||||
{
|
||||
_clientSocket.Receive(new byte[0]);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
+206
@@ -0,0 +1,206 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class Socks5Connector_Connect_NoAuthentication_Succeed : Socks5ConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private AsyncSocketListener _proxyServer;
|
||||
private Socket _clientSocket;
|
||||
private List<byte> _bytesReceivedByProxy;
|
||||
private Socket _actual;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
_connectionInfo = CreateConnectionInfo(new string('a', 255), new string('b', 255));
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(100);
|
||||
_bytesReceivedByProxy = new List<byte>();
|
||||
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
_proxyServer = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.ProxyPort));
|
||||
_proxyServer.BytesReceived += (bytesReceived, socket) =>
|
||||
{
|
||||
_bytesReceivedByProxy.AddRange(bytesReceived);
|
||||
|
||||
if (_bytesReceivedByProxy.Count == 4)
|
||||
{
|
||||
// We received the greeting
|
||||
|
||||
socket.Send(new byte[]
|
||||
{
|
||||
// SOCKS version
|
||||
0x05,
|
||||
// Require no authentication
|
||||
0x00
|
||||
});
|
||||
}
|
||||
else if (_bytesReceivedByProxy.Count == 4 + (1 + 1 + 1 + 1 + 4 + 2))
|
||||
{
|
||||
// We received the connection request
|
||||
|
||||
socket.Send(new byte[]
|
||||
{
|
||||
// SOCKS version
|
||||
0x05,
|
||||
// Connection successful
|
||||
0x00,
|
||||
// Reserved byte
|
||||
0x00,
|
||||
});
|
||||
|
||||
// Send server bound address
|
||||
socket.Send(new byte[]
|
||||
{
|
||||
// IPv6
|
||||
0x04,
|
||||
// IP address
|
||||
0x01,
|
||||
0x02,
|
||||
0x12,
|
||||
0x41,
|
||||
0x31,
|
||||
0x02,
|
||||
0x42,
|
||||
0x41,
|
||||
0x71,
|
||||
0x02,
|
||||
0x32,
|
||||
0x81,
|
||||
0x01,
|
||||
0x52,
|
||||
0x12,
|
||||
0x91,
|
||||
// Port
|
||||
0x0f,
|
||||
0x1b,
|
||||
});
|
||||
|
||||
// Send extra byte to allow us to verify that connector did not consume too much
|
||||
socket.Send(new byte[]
|
||||
{
|
||||
0xff
|
||||
});
|
||||
}
|
||||
};
|
||||
_proxyServer.Start();
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_proxyServer != null)
|
||||
{
|
||||
_proxyServer.Dispose();
|
||||
}
|
||||
|
||||
if (_clientSocket != null)
|
||||
{
|
||||
_clientSocket.Shutdown(SocketShutdown.Both);
|
||||
_clientSocket.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
_actual = Connector.Connect(_connectionInfo);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveReturnedSocketCreatedUsingSocketFactory()
|
||||
{
|
||||
Assert.IsNotNull(_actual);
|
||||
Assert.AreSame(_clientSocket, _actual);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldBeConnected()
|
||||
{
|
||||
Assert.IsTrue(_clientSocket.Connected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ProxyShouldHaveReceivedExpectedSocksRequest()
|
||||
{
|
||||
var expectedSocksRequest = new byte[]
|
||||
{
|
||||
//
|
||||
// Client greeting
|
||||
//
|
||||
|
||||
// SOCKS version
|
||||
0x05,
|
||||
// Number of authentication methods supported
|
||||
0x02,
|
||||
// No authentication
|
||||
0x00,
|
||||
// Username/password
|
||||
0x02,
|
||||
|
||||
//
|
||||
// Client connection request
|
||||
//
|
||||
|
||||
// SOCKS version
|
||||
0x05,
|
||||
// Establish a TCP/IP stream connection
|
||||
0x01,
|
||||
// Reserved
|
||||
0x00,
|
||||
// Destination address type (IPv4)
|
||||
0x01,
|
||||
// Destination address (IPv4)
|
||||
0x7f,
|
||||
0x00,
|
||||
0x00,
|
||||
0x01,
|
||||
// Destination port
|
||||
0x03,
|
||||
0x09
|
||||
|
||||
};
|
||||
|
||||
var errorText = string.Format("Expected:{0}{1}{0}but was:{0}{2}",
|
||||
Environment.NewLine,
|
||||
PacketDump.Create(expectedSocksRequest, 2),
|
||||
PacketDump.Create(_bytesReceivedByProxy, 2));
|
||||
|
||||
Assert.IsTrue(expectedSocksRequest.SequenceEqual(_bytesReceivedByProxy), errorText);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void OnlySocksResponseShouldHaveBeenConsumed()
|
||||
{
|
||||
var buffer = new byte[1];
|
||||
|
||||
var bytesRead = _clientSocket.Receive(buffer);
|
||||
Assert.AreEqual(1, bytesRead);
|
||||
Assert.AreEqual(0xff, buffer[0]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class Socks5ConnectorTest_Connect_ProxySocksVersionIsNotSupported : Socks5ConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private AsyncSocketListener _proxyServer;
|
||||
private Socket _clientSocket;
|
||||
private byte _proxySocksVersion;
|
||||
private bool _disconnected;
|
||||
private ProxyException _actualException;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
_connectionInfo = CreateConnectionInfo("proxyUser", "proxyPwd");
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(100);
|
||||
_proxySocksVersion = GetNotSupportedSocksVersion();
|
||||
_actualException = null;
|
||||
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
_proxyServer = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.ProxyPort));
|
||||
_proxyServer.Disconnected += socket => _disconnected = true;
|
||||
_proxyServer.BytesReceived += (bytesReceived, socket) =>
|
||||
{
|
||||
socket.Send(new byte[] { _proxySocksVersion });
|
||||
};
|
||||
_proxyServer.Start();
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_proxyServer != null)
|
||||
{
|
||||
_proxyServer.Dispose();
|
||||
}
|
||||
|
||||
if (_clientSocket != null)
|
||||
{
|
||||
_clientSocket.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
try
|
||||
{
|
||||
Connector.Connect(_connectionInfo);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ProxyException ex)
|
||||
{
|
||||
_actualException = ex;
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveThrownProxyException()
|
||||
{
|
||||
Assert.IsNotNull(_actualException);
|
||||
Assert.IsNull(_actualException.InnerException);
|
||||
Assert.AreEqual(string.Format("SOCKS Version '{0}' is not supported.", _proxySocksVersion), _actualException.Message);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectionToProxyShouldHaveBeenShutDown()
|
||||
{
|
||||
Assert.IsTrue(_disconnected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldHaveBeenDisposed()
|
||||
{
|
||||
try
|
||||
{
|
||||
_clientSocket.Receive(new byte[0]);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
|
||||
private static byte GetNotSupportedSocksVersion()
|
||||
{
|
||||
var random = new Random();
|
||||
|
||||
while (true)
|
||||
{
|
||||
var socksVersion = random.Next(1, 255);
|
||||
if (socksVersion != 5)
|
||||
{
|
||||
return (byte) socksVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Common;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class Socks5ConnectorTest_Connect_TimeoutConnectingToProxy : Socks5ConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private SshOperationTimeoutException _actualException;
|
||||
private Socket _clientSocket;
|
||||
private Stopwatch _stopWatch;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
var random = new Random();
|
||||
|
||||
_connectionInfo = CreateConnectionInfo("proxyUser", "proxyPwd");
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(random.Next(50, 200));
|
||||
_stopWatch = new Stopwatch();
|
||||
_actualException = null;
|
||||
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_clientSocket != null)
|
||||
{
|
||||
_clientSocket.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
_stopWatch.Start();
|
||||
|
||||
try
|
||||
{
|
||||
Connector.Connect(_connectionInfo);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshOperationTimeoutException ex)
|
||||
{
|
||||
_actualException = ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_stopWatch.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveThrownSshOperationTimeoutException()
|
||||
{
|
||||
Assert.IsNull(_actualException.InnerException);
|
||||
Assert.AreEqual(string.Format(CultureInfo.InvariantCulture, "Connection failed to establish within {0} milliseconds.", _connectionInfo.Timeout.TotalMilliseconds), _actualException.Message);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveRespectedTimeout()
|
||||
{
|
||||
var errorText = string.Format("Elapsed: {0}, Timeout: {1}",
|
||||
_stopWatch.ElapsedMilliseconds,
|
||||
_connectionInfo.Timeout.TotalMilliseconds);
|
||||
|
||||
Assert.IsTrue(_stopWatch.ElapsedMilliseconds >= _connectionInfo.Timeout.TotalMilliseconds, errorText);
|
||||
Assert.IsTrue(_stopWatch.ElapsedMilliseconds < (_connectionInfo.Timeout.TotalMilliseconds + 100), errorText);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldHaveBeenDisposed()
|
||||
{
|
||||
try
|
||||
{
|
||||
_clientSocket.Receive(new byte[0]);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class Socks5ConnectorTest_Connect_UserNamePasswordAuthentication_AuthenticationFailed : Socks5ConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private AsyncSocketListener _proxyServer;
|
||||
private Socket _clientSocket;
|
||||
private List<byte> _bytesReceivedByProxy;
|
||||
private bool _disconnected;
|
||||
private ProxyException _actualException;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
_connectionInfo = CreateConnectionInfo("aa", "bbbb");
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(100);
|
||||
_bytesReceivedByProxy = new List<byte>();
|
||||
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
_proxyServer = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.ProxyPort));
|
||||
_proxyServer.Disconnected += socket => _disconnected = true;
|
||||
_proxyServer.BytesReceived += (bytesReceived, socket) =>
|
||||
{
|
||||
_bytesReceivedByProxy.AddRange(bytesReceived);
|
||||
|
||||
if (_bytesReceivedByProxy.Count == 4)
|
||||
{
|
||||
// We received the greeting
|
||||
|
||||
socket.Send(new byte[]
|
||||
{
|
||||
// SOCKS version
|
||||
0x05,
|
||||
// Require username/password authentication
|
||||
0x02
|
||||
});
|
||||
}
|
||||
else if (_bytesReceivedByProxy.Count == 4 + (1 + 1 + 2 + 1 + 4))
|
||||
{
|
||||
// We received the username/password authentication request
|
||||
|
||||
socket.Send(new byte[]
|
||||
{
|
||||
// Authentication version
|
||||
0x01,
|
||||
// Authentication failed
|
||||
0x01
|
||||
});
|
||||
}
|
||||
};
|
||||
_proxyServer.Start();
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_proxyServer != null)
|
||||
{
|
||||
_proxyServer.Dispose();
|
||||
}
|
||||
|
||||
if (_clientSocket != null)
|
||||
{
|
||||
_clientSocket.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
try
|
||||
{
|
||||
Connector.Connect(_connectionInfo);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ProxyException ex)
|
||||
{
|
||||
_actualException = ex;
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveThrownProxyException()
|
||||
{
|
||||
Assert.IsNotNull(_actualException);
|
||||
Assert.IsNull(_actualException.InnerException);
|
||||
Assert.AreEqual("SOCKS5: Username/Password authentication failed.", _actualException.Message);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ProxyShouldHaveReceivedExpectedSocksRequest()
|
||||
{
|
||||
var expectedSocksRequest = new List<byte>();
|
||||
|
||||
//
|
||||
// Client greeting
|
||||
//
|
||||
|
||||
// SOCKS version
|
||||
expectedSocksRequest.Add(0x05);
|
||||
// Number of authentication methods supported
|
||||
expectedSocksRequest.Add(0x02);
|
||||
// No authentication
|
||||
expectedSocksRequest.Add(0x00);
|
||||
// Username/password
|
||||
expectedSocksRequest.Add(0x02);
|
||||
|
||||
//
|
||||
// Username/password authentication request
|
||||
//
|
||||
|
||||
// Version of the negotiation
|
||||
expectedSocksRequest.Add(0x01);
|
||||
// Length of the username
|
||||
expectedSocksRequest.Add((byte) _connectionInfo.ProxyUsername.Length);
|
||||
// Username
|
||||
expectedSocksRequest.AddRange(Encoding.ASCII.GetBytes(_connectionInfo.ProxyUsername));
|
||||
// Length of the password
|
||||
expectedSocksRequest.Add((byte) _connectionInfo.ProxyPassword.Length);
|
||||
// Password
|
||||
expectedSocksRequest.AddRange(Encoding.ASCII.GetBytes(_connectionInfo.ProxyPassword));
|
||||
|
||||
var errorText = string.Format("Expected:{0}{1}{0}but was:{0}{2}",
|
||||
Environment.NewLine,
|
||||
PacketDump.Create(expectedSocksRequest, 2),
|
||||
PacketDump.Create(_bytesReceivedByProxy, 2));
|
||||
|
||||
Assert.IsTrue(expectedSocksRequest.SequenceEqual(_bytesReceivedByProxy), errorText);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectionToProxyShouldHaveBeenShutDown()
|
||||
{
|
||||
Assert.IsTrue(_disconnected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldHaveBeenDisposed()
|
||||
{
|
||||
try
|
||||
{
|
||||
_clientSocket.Receive(new byte[0]);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
+220
@@ -0,0 +1,220 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class Socks5ConnectorTest_Connect_UserNamePasswordAuthentication_ConnectionSucceeded : Socks5ConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private AsyncSocketListener _proxyServer;
|
||||
private Socket _clientSocket;
|
||||
private List<byte> _bytesReceivedByProxy;
|
||||
private Socket _actual;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
_connectionInfo = CreateConnectionInfo(GenerateRandomString(0, 255), GenerateRandomString(0, 255));
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(100);
|
||||
_bytesReceivedByProxy = new List<byte>();
|
||||
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
_proxyServer = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.ProxyPort));
|
||||
_proxyServer.BytesReceived += (bytesReceived, socket) =>
|
||||
{
|
||||
_bytesReceivedByProxy.AddRange(bytesReceived);
|
||||
|
||||
if (_bytesReceivedByProxy.Count == 4)
|
||||
{
|
||||
// We received the greeting
|
||||
|
||||
socket.Send(new byte[]
|
||||
{
|
||||
// SOCKS version
|
||||
0x05,
|
||||
// Require username/password authentication
|
||||
0x02
|
||||
});
|
||||
}
|
||||
else if (_bytesReceivedByProxy.Count == 4 + (1 + 1 + _connectionInfo.ProxyUsername.Length + 1 + _connectionInfo.ProxyPassword.Length))
|
||||
{
|
||||
// We received the username/password authentication request
|
||||
|
||||
socket.Send(new byte[]
|
||||
{
|
||||
// Authentication version
|
||||
0x01,
|
||||
// Authentication successful
|
||||
0x00
|
||||
});
|
||||
}
|
||||
else if (_bytesReceivedByProxy.Count == 4 + (1 + 1 + _connectionInfo.ProxyUsername.Length + 1 + _connectionInfo.ProxyPassword.Length) + (1 + 1 + 1 + 1 + 4 + 2))
|
||||
{
|
||||
// We received the connection request
|
||||
|
||||
socket.Send(new byte[]
|
||||
{
|
||||
// SOCKS version
|
||||
0x05,
|
||||
// Connection successful
|
||||
0x00,
|
||||
// Reserved byte
|
||||
0x00,
|
||||
});
|
||||
|
||||
// Send server bound address
|
||||
socket.Send(new byte[]
|
||||
{
|
||||
// IPv4
|
||||
0x01,
|
||||
// IP address
|
||||
0x01,
|
||||
0x02,
|
||||
0x12,
|
||||
0x41,
|
||||
// Port
|
||||
0x01,
|
||||
0x02,
|
||||
});
|
||||
|
||||
// Send extra byte to allow us to verify that connector did not consume too much
|
||||
socket.Send(new byte[]
|
||||
{
|
||||
0xfe
|
||||
});
|
||||
}
|
||||
};
|
||||
_proxyServer.Start();
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_proxyServer != null)
|
||||
{
|
||||
_proxyServer.Dispose();
|
||||
}
|
||||
|
||||
if (_clientSocket != null)
|
||||
{
|
||||
_clientSocket.Shutdown(SocketShutdown.Both);
|
||||
_clientSocket.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
_actual = Connector.Connect(_connectionInfo);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveReturnedSocketCreatedUsingSocketFactory()
|
||||
{
|
||||
Assert.IsNotNull(_actual);
|
||||
Assert.AreSame(_clientSocket, _actual);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldBeConnected()
|
||||
{
|
||||
Assert.IsTrue(_clientSocket.Connected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ProxyShouldHaveReceivedExpectedSocksRequest()
|
||||
{
|
||||
var expectedSocksRequest = new List<byte>();
|
||||
|
||||
//
|
||||
// Client greeting
|
||||
//
|
||||
|
||||
// SOCKS version
|
||||
expectedSocksRequest.Add(0x05);
|
||||
// Number of authentication methods supported
|
||||
expectedSocksRequest.Add(0x02);
|
||||
// No authentication
|
||||
expectedSocksRequest.Add(0x00);
|
||||
// Username/password
|
||||
expectedSocksRequest.Add(0x02);
|
||||
|
||||
//
|
||||
// Username/password authentication request
|
||||
//
|
||||
|
||||
// Version of the negotiation
|
||||
expectedSocksRequest.Add(0x01);
|
||||
// Length of the username
|
||||
expectedSocksRequest.Add((byte)_connectionInfo.ProxyUsername.Length);
|
||||
// Username
|
||||
expectedSocksRequest.AddRange(Encoding.ASCII.GetBytes(_connectionInfo.ProxyUsername));
|
||||
// Length of the password
|
||||
expectedSocksRequest.Add((byte)_connectionInfo.ProxyPassword.Length);
|
||||
// Password
|
||||
expectedSocksRequest.AddRange(Encoding.ASCII.GetBytes(_connectionInfo.ProxyPassword));
|
||||
|
||||
//
|
||||
// Client connection request
|
||||
//
|
||||
|
||||
// SOCKS version
|
||||
expectedSocksRequest.Add(0x05);
|
||||
// Establish a TCP/IP stream connection
|
||||
expectedSocksRequest.Add(0x01);
|
||||
// Reserved
|
||||
expectedSocksRequest.Add(0x00);
|
||||
// Destination address type (IPv4)
|
||||
expectedSocksRequest.Add(0x01);
|
||||
// Destination address (IPv4)
|
||||
expectedSocksRequest.Add(0x7f);
|
||||
expectedSocksRequest.Add(0x00);
|
||||
expectedSocksRequest.Add(0x00);
|
||||
expectedSocksRequest.Add(0x01);
|
||||
// Destination port
|
||||
expectedSocksRequest.Add(0x03);
|
||||
expectedSocksRequest.Add(0x09);
|
||||
|
||||
var errorText = string.Format("Expected:{0}{1}{0}but was:{0}{2}",
|
||||
Environment.NewLine,
|
||||
PacketDump.Create(expectedSocksRequest, 2),
|
||||
PacketDump.Create(_bytesReceivedByProxy, 2));
|
||||
|
||||
Assert.IsTrue(expectedSocksRequest.SequenceEqual(_bytesReceivedByProxy), errorText);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void OnlySocksResponseShouldHaveBeenConsumed()
|
||||
{
|
||||
var buffer = new byte[1];
|
||||
|
||||
var bytesRead = _clientSocket.Receive(buffer);
|
||||
Assert.AreEqual(1, bytesRead);
|
||||
Assert.AreEqual(0xfe, buffer[0]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class Socks5ConnectorTest_Connect_UserNamePasswordAuthentication_PasswordExceedsMaximumLength : Socks5ConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private AsyncSocketListener _proxyServer;
|
||||
private Socket _clientSocket;
|
||||
private List<byte> _bytesReceivedByProxy;
|
||||
private bool _disconnected;
|
||||
private ProxyException _actualException;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
_connectionInfo = CreateConnectionInfo(new string('a', 255), new string('b', 256));
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(100);
|
||||
_bytesReceivedByProxy = new List<byte>();
|
||||
_actualException = null;
|
||||
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
_proxyServer = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.ProxyPort));
|
||||
_proxyServer.Disconnected += socket => _disconnected = true;
|
||||
_proxyServer.BytesReceived += (bytesReceived, socket) =>
|
||||
{
|
||||
_bytesReceivedByProxy.AddRange(bytesReceived);
|
||||
|
||||
// Wait until we received the greeting
|
||||
if (_bytesReceivedByProxy.Count == 4)
|
||||
{
|
||||
socket.Send(new byte[]
|
||||
{
|
||||
// SOCKS version
|
||||
0x05,
|
||||
// Username/password authentication
|
||||
0x02
|
||||
});
|
||||
}
|
||||
};
|
||||
_proxyServer.Start();
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_proxyServer != null)
|
||||
{
|
||||
_proxyServer.Dispose();
|
||||
}
|
||||
|
||||
if (_clientSocket != null)
|
||||
{
|
||||
_clientSocket.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
try
|
||||
{
|
||||
Connector.Connect(_connectionInfo);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ProxyException ex)
|
||||
{
|
||||
_actualException = ex;
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveThrownProxyException()
|
||||
{
|
||||
Assert.IsNotNull(_actualException);
|
||||
Assert.IsNull(_actualException.InnerException);
|
||||
Assert.AreEqual("Proxy password is too long.", _actualException.Message);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ProxyShouldHaveReceivedExpectedSocksRequest()
|
||||
{
|
||||
var expectedSocksRequest = new List<byte>();
|
||||
|
||||
//
|
||||
// Client greeting
|
||||
//
|
||||
|
||||
// SOCKS version
|
||||
expectedSocksRequest.Add(0x05);
|
||||
// Number of authentication methods supported
|
||||
expectedSocksRequest.Add(0x02);
|
||||
// No authentication
|
||||
expectedSocksRequest.Add(0x00);
|
||||
// Username/password
|
||||
expectedSocksRequest.Add(0x02);
|
||||
|
||||
var errorText = string.Format("Expected:{0}{1}{0}but was:{0}{2}",
|
||||
Environment.NewLine,
|
||||
PacketDump.Create(expectedSocksRequest, 2),
|
||||
PacketDump.Create(_bytesReceivedByProxy, 2));
|
||||
|
||||
Assert.IsTrue(expectedSocksRequest.SequenceEqual(_bytesReceivedByProxy), errorText);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectionToProxyShouldHaveBeenShutDown()
|
||||
{
|
||||
Assert.IsTrue(_disconnected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldHaveBeenDisposed()
|
||||
{
|
||||
try
|
||||
{
|
||||
_clientSocket.Receive(new byte[0]);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Connection
|
||||
{
|
||||
[TestClass]
|
||||
public class Socks5ConnectorTest_Connect_UserNamePasswordAuthentication_UserNameExceedsMaximumLength : Socks5ConnectorTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private AsyncSocketListener _proxyServer;
|
||||
private Socket _clientSocket;
|
||||
private List<byte> _bytesReceivedByProxy;
|
||||
private bool _disconnected;
|
||||
private ProxyException _actualException;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
_connectionInfo = CreateConnectionInfo(new string('a', 256), new string('b', 255));
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(100);
|
||||
_bytesReceivedByProxy = new List<byte>();
|
||||
_actualException = null;
|
||||
|
||||
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
_proxyServer = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.ProxyPort));
|
||||
_proxyServer.Disconnected += socket => _disconnected = true;
|
||||
_proxyServer.BytesReceived += (bytesReceived, socket) =>
|
||||
{
|
||||
_bytesReceivedByProxy.AddRange(bytesReceived);
|
||||
|
||||
// Wait until we received the greeting
|
||||
if (_bytesReceivedByProxy.Count == 4)
|
||||
{
|
||||
socket.Send(new byte[]
|
||||
{
|
||||
// SOCKS version
|
||||
0x05,
|
||||
// Username/password authentication
|
||||
0x02
|
||||
});
|
||||
}
|
||||
};
|
||||
_proxyServer.Start();
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
.Returns(_clientSocket);
|
||||
}
|
||||
|
||||
protected override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
|
||||
if (_proxyServer != null)
|
||||
{
|
||||
_proxyServer.Dispose();
|
||||
}
|
||||
|
||||
if (_clientSocket != null)
|
||||
{
|
||||
_clientSocket.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
try
|
||||
{
|
||||
Connector.Connect(_connectionInfo);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ProxyException ex)
|
||||
{
|
||||
_actualException = ex;
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldHaveThrownProxyException()
|
||||
{
|
||||
Assert.IsNotNull(_actualException);
|
||||
Assert.IsNull(_actualException.InnerException);
|
||||
Assert.AreEqual("Proxy username is too long.", _actualException.Message);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ProxyShouldHaveReceivedExpectedSocksRequest()
|
||||
{
|
||||
var expectedSocksRequest = new List<byte>();
|
||||
|
||||
//
|
||||
// Client greeting
|
||||
//
|
||||
|
||||
// SOCKS version
|
||||
expectedSocksRequest.Add(0x05);
|
||||
// Number of authentication methods supported
|
||||
expectedSocksRequest.Add(0x02);
|
||||
// No authentication
|
||||
expectedSocksRequest.Add(0x00);
|
||||
// Username/password
|
||||
expectedSocksRequest.Add(0x02);
|
||||
|
||||
var errorText = string.Format("Expected:{0}{1}{0}but was:{0}{2}",
|
||||
Environment.NewLine,
|
||||
PacketDump.Create(expectedSocksRequest, 2),
|
||||
PacketDump.Create(_bytesReceivedByProxy, 2));
|
||||
|
||||
Assert.IsTrue(expectedSocksRequest.SequenceEqual(_bytesReceivedByProxy), errorText);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectionToProxyShouldHaveBeenShutDown()
|
||||
{
|
||||
Assert.IsTrue(_disconnected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldHaveBeenDisposed()
|
||||
{
|
||||
try
|
||||
{
|
||||
_clientSocket.Receive(new byte[0]);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
||||
Times.Once());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using Moq;
|
||||
using Renci.SshNet.NetConf;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
public abstract class NetConfClientTestBase : BaseClientTestBase
|
||||
{
|
||||
internal Mock<INetConfSession> _netConfSessionMock { get; private set; }
|
||||
|
||||
protected override void CreateMocks()
|
||||
{
|
||||
base.CreateMocks();
|
||||
|
||||
_netConfSessionMock = new Mock<INetConfSession>(MockBehavior.Strict);
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
-31
@@ -10,51 +10,29 @@ using Renci.SshNet.Security;
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class NetConfClientTest_Connect_NetConfSessionConnectFailure
|
||||
public class NetConfClientTest_Connect_NetConfSessionConnectFailure : NetConfClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private Mock<INetConfSession> _netConfSessionMock;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private ApplicationException _netConfSessionConnectionException;
|
||||
private NetConfClient _netConfClient;
|
||||
private ApplicationException _actualException;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
}
|
||||
|
||||
private void Arrange()
|
||||
{
|
||||
SetupData();
|
||||
CreateMocks();
|
||||
SetupMocks();
|
||||
|
||||
_netConfClient = new NetConfClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
}
|
||||
|
||||
private void SetupData()
|
||||
protected override void SetupData()
|
||||
{
|
||||
_connectionInfo = new ConnectionInfo("host", "user", new NoneAuthenticationMethod("userauth"));
|
||||
_netConfSessionConnectionException = new ApplicationException();
|
||||
_netConfClient = new NetConfClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
}
|
||||
|
||||
private void CreateMocks()
|
||||
{
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
_netConfSessionMock = new Mock<INetConfSession>(MockBehavior.Strict);
|
||||
}
|
||||
|
||||
private void SetupMocks()
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
var sequence = new MockSequence();
|
||||
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence)
|
||||
.Setup(p => p.Connect());
|
||||
@@ -70,7 +48,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
.Setup(p => p.Dispose());
|
||||
}
|
||||
|
||||
private void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -6,56 +6,55 @@ using System;
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class NetConfClientTest_Dispose_Connected
|
||||
public class NetConfClientTest_Dispose_Connected : NetConfClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private Mock<INetConfSession> _netConfSessionMock;
|
||||
private NetConfClient _netConfClient;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private int _operationTimeout;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
protected override void SetupData()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
}
|
||||
|
||||
protected void Arrange()
|
||||
{
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
_netConfSessionMock = new Mock<INetConfSession>(MockBehavior.Strict);
|
||||
|
||||
_connectionInfo = new ConnectionInfo("host", "user", new NoneAuthenticationMethod("userauth"));
|
||||
_operationTimeout = new Random().Next(1000, 10000);
|
||||
_netConfClient = new NetConfClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
_netConfClient.OperationTimeout = TimeSpan.FromMilliseconds(_operationTimeout);
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
var sequence = new MockSequence();
|
||||
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateNetConfSession(_sessionMock.Object, _operationTimeout))
|
||||
.Returns(_netConfSessionMock.Object);
|
||||
_netConfSessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.OnDisconnecting());
|
||||
_netConfSessionMock.InSequence(sequence).Setup(p => p.Disconnect());
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Dispose());
|
||||
_netConfSessionMock.InSequence(sequence).Setup(p => p.Dispose());
|
||||
.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence)
|
||||
.Setup(p => p.Connect());
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateNetConfSession(_sessionMock.Object, _operationTimeout))
|
||||
.Returns(_netConfSessionMock.Object);
|
||||
_netConfSessionMock.InSequence(sequence)
|
||||
.Setup(p => p.Connect());
|
||||
_sessionMock.InSequence(sequence)
|
||||
.Setup(p => p.OnDisconnecting());
|
||||
_netConfSessionMock.InSequence(sequence)
|
||||
.Setup(p => p.Disconnect());
|
||||
_sessionMock.InSequence(sequence)
|
||||
.Setup(p => p.Dispose());
|
||||
_netConfSessionMock.InSequence(sequence)
|
||||
.Setup(p => p.Dispose());
|
||||
}
|
||||
|
||||
protected override void Arrange()
|
||||
{
|
||||
base.Arrange();
|
||||
|
||||
_netConfClient.Connect();
|
||||
}
|
||||
|
||||
protected void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
_netConfClient.Dispose();
|
||||
}
|
||||
@@ -66,10 +65,17 @@ namespace Renci.SshNet.Tests.Classes
|
||||
_serviceFactoryMock.Verify(p => p.CreateNetConfSession(_sessionMock.Object, _operationTimeout), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSocketFactoryOnServiceFactoryShouldBeInvokedOnce()
|
||||
{
|
||||
_serviceFactoryMock.Verify(p => p.CreateSocketFactory(), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSessionOnServiceFactoryShouldBeInvokedOnce()
|
||||
{
|
||||
_serviceFactoryMock.Verify(p => p.CreateSession(_connectionInfo), Times.Once);
|
||||
_serviceFactoryMock.Verify(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
@@ -6,11 +6,8 @@ using System;
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class NetConfClientTest_Dispose_Disconnected
|
||||
public class NetConfClientTest_Dispose_Disconnected : NetConfClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private Mock<INetConfSession> _netConfSessionMock;
|
||||
private NetConfClient _netConfClient;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private int _operationTimeout;
|
||||
@@ -27,37 +24,45 @@ namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
}
|
||||
|
||||
protected void Arrange()
|
||||
protected override void SetupData()
|
||||
{
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
_netConfSessionMock = new Mock<INetConfSession>(MockBehavior.Strict);
|
||||
|
||||
_connectionInfo = new ConnectionInfo("host", "user", new NoneAuthenticationMethod("userauth"));
|
||||
_operationTimeout = new Random().Next(1000, 10000);
|
||||
_netConfClient = new NetConfClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
_netConfClient.OperationTimeout = TimeSpan.FromMilliseconds(_operationTimeout);
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
var sequence = new MockSequence();
|
||||
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Returns(_sessionMock.Object);
|
||||
.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateNetConfSession(_sessionMock.Object, _operationTimeout))
|
||||
.Returns(_netConfSessionMock.Object);
|
||||
.Setup(p => p.CreateNetConfSession(_sessionMock.Object, _operationTimeout))
|
||||
.Returns(_netConfSessionMock.Object);
|
||||
_netConfSessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.OnDisconnecting());
|
||||
_netConfSessionMock.InSequence(sequence).Setup(p => p.Disconnect());
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Dispose());
|
||||
_netConfSessionMock.InSequence(sequence).Setup(p => p.Disconnect());
|
||||
_netConfSessionMock.InSequence(sequence).Setup(p => p.Dispose());
|
||||
}
|
||||
|
||||
protected override void Arrange()
|
||||
{
|
||||
base.Arrange();
|
||||
|
||||
_netConfClient.Connect();
|
||||
_netConfClient.Disconnect();
|
||||
}
|
||||
|
||||
protected void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
_netConfClient.Dispose();
|
||||
}
|
||||
@@ -68,10 +73,17 @@ namespace Renci.SshNet.Tests.Classes
|
||||
_serviceFactoryMock.Verify(p => p.CreateNetConfSession(_sessionMock.Object, _operationTimeout), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSocketFactoryOnServiceFactoryShouldBeInvokedOnce()
|
||||
{
|
||||
_serviceFactoryMock.Verify(p => p.CreateSocketFactory(), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSessionOnServiceFactoryShouldBeInvokedOnce()
|
||||
{
|
||||
_serviceFactoryMock.Verify(p => p.CreateSession(_connectionInfo), Times.Once);
|
||||
_serviceFactoryMock.Verify(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
@@ -6,57 +6,50 @@ using System;
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class NetConfClientTest_Dispose_Disposed
|
||||
public class NetConfClientTest_Dispose_Disposed : NetConfClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private Mock<INetConfSession> _netConfSessionMock;
|
||||
private NetConfClient _netConfClient;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private int _operationTimeout;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
protected override void SetupData()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
}
|
||||
|
||||
protected void Arrange()
|
||||
{
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
_netConfSessionMock = new Mock<INetConfSession>(MockBehavior.Strict);
|
||||
|
||||
_connectionInfo = new ConnectionInfo("host", "user", new NoneAuthenticationMethod("userauth"));
|
||||
_operationTimeout = new Random().Next(1000, 10000);
|
||||
_netConfClient = new NetConfClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
_netConfClient.OperationTimeout = TimeSpan.FromMilliseconds(_operationTimeout);
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
var sequence = new MockSequence();
|
||||
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Returns(_sessionMock.Object);
|
||||
.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateNetConfSession(_sessionMock.Object, _operationTimeout))
|
||||
.Returns(_netConfSessionMock.Object);
|
||||
.Setup(p => p.CreateNetConfSession(_sessionMock.Object, _operationTimeout))
|
||||
.Returns(_netConfSessionMock.Object);
|
||||
_netConfSessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.OnDisconnecting());
|
||||
_netConfSessionMock.InSequence(sequence).Setup(p => p.Disconnect());
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Dispose());
|
||||
_netConfSessionMock.InSequence(sequence).Setup(p => p.Dispose());
|
||||
}
|
||||
|
||||
protected override void Arrange()
|
||||
{
|
||||
base.Arrange();
|
||||
|
||||
_netConfClient.Connect();
|
||||
_netConfClient.Dispose();
|
||||
}
|
||||
|
||||
protected void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
_netConfClient.Dispose();
|
||||
}
|
||||
@@ -67,10 +60,17 @@ namespace Renci.SshNet.Tests.Classes
|
||||
_serviceFactoryMock.Verify(p => p.CreateNetConfSession(_sessionMock.Object, _operationTimeout), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSocketFactoryOnServiceFactoryShouldBeInvokedOnce()
|
||||
{
|
||||
_serviceFactoryMock.Verify(p => p.CreateSocketFactory(), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSessionOnServiceFactoryShouldBeInvokedOnce()
|
||||
{
|
||||
_serviceFactoryMock.Verify(p => p.CreateSession(_connectionInfo), Times.Once);
|
||||
_serviceFactoryMock.Verify(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
@@ -1,59 +1,58 @@
|
||||
using System;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.NetConf;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class NetConfClientTest_Finalize_Connected
|
||||
public class NetConfClientTest_Finalize_Connected : NetConfClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private Mock<INetConfSession> _netConfSessionMock;
|
||||
private NetConfClient _netConfClient;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private int _operationTimeout;
|
||||
private WeakReference _netConfClientWeakRefence;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
protected override void SetupData()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
}
|
||||
|
||||
protected void Arrange()
|
||||
{
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Loose);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Loose);
|
||||
_netConfSessionMock = new Mock<INetConfSession>(MockBehavior.Loose);
|
||||
|
||||
_connectionInfo = new ConnectionInfo("host", "user", new NoneAuthenticationMethod("userauth"));
|
||||
_operationTimeout = new Random().Next(1000, 10000);
|
||||
_netConfClient = new NetConfClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
_netConfClient.OperationTimeout = TimeSpan.FromMilliseconds(_operationTimeout);
|
||||
_netConfClientWeakRefence = new WeakReference(_netConfClient);
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
var sequence = new MockSequence();
|
||||
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateNetConfSession(_sessionMock.Object, _operationTimeout))
|
||||
.Returns(_netConfSessionMock.Object);
|
||||
_netConfSessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence)
|
||||
.Setup(p => p.Connect());
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateNetConfSession(_sessionMock.Object, _operationTimeout))
|
||||
.Returns(_netConfSessionMock.Object);
|
||||
_netConfSessionMock.InSequence(sequence)
|
||||
.Setup(p => p.Connect());
|
||||
}
|
||||
|
||||
protected override void Arrange()
|
||||
{
|
||||
base.Arrange();
|
||||
|
||||
_netConfClient.Connect();
|
||||
_netConfClient = null;
|
||||
|
||||
// we need to dereference all other mocks as they might otherwise hold the target alive
|
||||
_sessionMock = null;
|
||||
_connectionInfo = null;
|
||||
_serviceFactoryMock = null;
|
||||
|
||||
// We need to dereference all mocks as they might otherwise hold the target alive
|
||||
//(through recorded invocations?)
|
||||
CreateMocks();
|
||||
}
|
||||
|
||||
protected void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
@@ -62,13 +61,25 @@ namespace Renci.SshNet.Tests.Classes
|
||||
[TestMethod]
|
||||
public void DisconnectOnNetConfSessionShouldBeInvokedOnce()
|
||||
{
|
||||
// Since we recreated the mocks, this test has no value
|
||||
// We'll leaving ths test just in case we have a solution that does not require us
|
||||
// to recreate the mocks
|
||||
_netConfSessionMock.Verify(p => p.Disconnect(), Times.Never);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DisposeOnNetConfSessionShouldBeInvokedOnce()
|
||||
{
|
||||
// Since we recreated the mocks, this test has no value
|
||||
// We'll leaving ths test just in case we have a solution that does not require us
|
||||
// to recreate the mocks
|
||||
_netConfSessionMock.Verify(p => p.Dispose(), Times.Never);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void NetConfClientShouldHaveBeenFinalized()
|
||||
{
|
||||
Assert.IsNull(_netConfClientWeakRefence.Target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,45 +1,22 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Moq;
|
||||
using Renci.SshNet.Channels;
|
||||
using Renci.SshNet.Common;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
public abstract class ScpClientTestBase
|
||||
public abstract class ScpClientTestBase : BaseClientTestBase
|
||||
{
|
||||
internal Mock<IServiceFactory> _serviceFactoryMock;
|
||||
internal Mock<IRemotePathTransformation> _remotePathTransformationMock;
|
||||
internal Mock<ISession> _sessionMock;
|
||||
internal Mock<IChannelSession> _channelSessionMock;
|
||||
internal Mock<PipeStream> _pipeStreamMock;
|
||||
|
||||
protected abstract void SetupData();
|
||||
|
||||
protected void CreateMocks()
|
||||
protected override void CreateMocks()
|
||||
{
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
base.CreateMocks();
|
||||
|
||||
_remotePathTransformationMock = new Mock<IRemotePathTransformation>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
_channelSessionMock = new Mock<IChannelSession>(MockBehavior.Strict);
|
||||
_pipeStreamMock = new Mock<PipeStream>(MockBehavior.Strict);
|
||||
}
|
||||
|
||||
protected abstract void SetupMocks();
|
||||
|
||||
protected virtual void Arrange()
|
||||
{
|
||||
SetupData();
|
||||
CreateMocks();
|
||||
SetupMocks();
|
||||
}
|
||||
|
||||
[TestInitialize]
|
||||
public void Initialize()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
}
|
||||
|
||||
protected abstract void Act();
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -38,7 +38,10 @@ namespace Renci.SshNet.Tests.Classes
|
||||
.Setup(p => p.CreateRemotePathDoubleQuoteTransformation())
|
||||
.Returns(_remotePathTransformationMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
_serviceFactoryMock.InSequence(sequence).Setup(p => p.CreatePipeStream()).Returns(_pipeStreamMock.Object);
|
||||
|
||||
+4
-1
@@ -38,7 +38,10 @@ namespace Renci.SshNet.Tests.Classes
|
||||
.Setup(p => p.CreateRemotePathDoubleQuoteTransformation())
|
||||
.Returns(_remotePathTransformationMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
_serviceFactoryMock.InSequence(sequence).Setup(p => p.CreatePipeStream()).Returns(_pipeStreamMock.Object);
|
||||
|
||||
+4
-1
@@ -47,7 +47,10 @@ namespace Renci.SshNet.Tests.Classes
|
||||
.Setup(p => p.CreateRemotePathDoubleQuoteTransformation())
|
||||
.Returns(_remotePathTransformationMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
_serviceFactoryMock.InSequence(sequence).Setup(p => p.CreatePipeStream()).Returns(_pipeStreamMock.Object);
|
||||
|
||||
+4
-1
@@ -37,7 +37,10 @@ namespace Renci.SshNet.Tests.Classes
|
||||
.Setup(p => p.CreateRemotePathDoubleQuoteTransformation())
|
||||
.Returns(_remotePathTransformationMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
_serviceFactoryMock.InSequence(sequence).Setup(p => p.CreatePipeStream()).Returns(_pipeStreamMock.Object);
|
||||
|
||||
+4
-1
@@ -53,7 +53,10 @@ namespace Renci.SshNet.Tests.Classes
|
||||
.Setup(p => p.CreateRemotePathDoubleQuoteTransformation())
|
||||
.Returns(_remotePathTransformationMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
_serviceFactoryMock.InSequence(sequence).Setup(p => p.CreatePipeStream()).Returns(_pipeStreamMock.Object);
|
||||
|
||||
@@ -60,7 +60,10 @@ namespace Renci.SshNet.Tests.Classes
|
||||
.Setup(p => p.CreateRemotePathDoubleQuoteTransformation())
|
||||
.Returns(_remotePathTransformationMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
_serviceFactoryMock.InSequence(sequence).Setup(p => p.CreatePipeStream()).Returns(_pipeStreamMock.Object);
|
||||
|
||||
+4
-1
@@ -50,7 +50,10 @@ namespace Renci.SshNet.Tests.Classes
|
||||
.Setup(p => p.CreateRemotePathDoubleQuoteTransformation())
|
||||
.Returns(_remotePathTransformationMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
_serviceFactoryMock.InSequence(sequence).Setup(p => p.CreatePipeStream()).Returns(_pipeStreamMock.Object);
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
private ServiceFactory _serviceFactory;
|
||||
private Mock<IConnectionInfo> _connectionInfoMock;
|
||||
private Mock<ISocketFactory> _socketFactoryMock;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
@@ -25,7 +26,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
|
||||
try
|
||||
{
|
||||
_serviceFactory.CreateConnector(connectionInfo);
|
||||
_serviceFactory.CreateConnector(connectionInfo, _socketFactoryMock.Object);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ArgumentNullException ex)
|
||||
@@ -35,16 +36,36 @@ namespace Renci.SshNet.Tests.Classes
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SocketFactoryIsNull()
|
||||
{
|
||||
const ISocketFactory socketFactory = null;
|
||||
|
||||
try
|
||||
{
|
||||
_serviceFactory.CreateConnector(_connectionInfoMock.Object, socketFactory);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ArgumentNullException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("socketFactory", ex.ParamName);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ProxyType_Http()
|
||||
{
|
||||
_connectionInfoMock.Setup(p => p.ProxyType).Returns(ProxyTypes.Http);
|
||||
|
||||
var actual = _serviceFactory.CreateConnector(_connectionInfoMock.Object);
|
||||
var actual = _serviceFactory.CreateConnector(_connectionInfoMock.Object, _socketFactoryMock.Object);
|
||||
|
||||
Assert.IsNotNull(actual);
|
||||
Assert.AreEqual(typeof(HttpConnector), actual.GetType());
|
||||
|
||||
var httpConnector = (HttpConnector) actual;
|
||||
Assert.AreSame(_socketFactoryMock.Object, httpConnector.SocketFactory);
|
||||
|
||||
_connectionInfoMock.Verify(p => p.ProxyType, Times.Once);
|
||||
}
|
||||
|
||||
@@ -53,11 +74,14 @@ namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
_connectionInfoMock.Setup(p => p.ProxyType).Returns(ProxyTypes.None);
|
||||
|
||||
var actual = _serviceFactory.CreateConnector(_connectionInfoMock.Object);
|
||||
var actual = _serviceFactory.CreateConnector(_connectionInfoMock.Object, _socketFactoryMock.Object);
|
||||
|
||||
Assert.IsNotNull(actual);
|
||||
Assert.AreEqual(typeof(DirectConnector), actual.GetType());
|
||||
|
||||
var directConnector = (DirectConnector) actual;
|
||||
Assert.AreSame(_socketFactoryMock.Object, directConnector.SocketFactory);
|
||||
|
||||
_connectionInfoMock.Verify(p => p.ProxyType, Times.Once);
|
||||
}
|
||||
|
||||
@@ -66,11 +90,14 @@ namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
_connectionInfoMock.Setup(p => p.ProxyType).Returns(ProxyTypes.Socks4);
|
||||
|
||||
var actual = _serviceFactory.CreateConnector(_connectionInfoMock.Object);
|
||||
var actual = _serviceFactory.CreateConnector(_connectionInfoMock.Object, _socketFactoryMock.Object);
|
||||
|
||||
Assert.IsNotNull(actual);
|
||||
Assert.AreEqual(typeof(Socks4Connector), actual.GetType());
|
||||
|
||||
var socks4Connector = (Socks4Connector) actual;
|
||||
Assert.AreSame(_socketFactoryMock.Object, socks4Connector.SocketFactory);
|
||||
|
||||
_connectionInfoMock.Verify(p => p.ProxyType, Times.Once);
|
||||
}
|
||||
|
||||
@@ -79,11 +106,33 @@ namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
_connectionInfoMock.Setup(p => p.ProxyType).Returns(ProxyTypes.Socks5);
|
||||
|
||||
var actual = _serviceFactory.CreateConnector(_connectionInfoMock.Object);
|
||||
var actual = _serviceFactory.CreateConnector(_connectionInfoMock.Object, _socketFactoryMock.Object);
|
||||
|
||||
Assert.IsNotNull(actual);
|
||||
Assert.AreEqual(typeof(Socks5Connector), actual.GetType());
|
||||
|
||||
var socks5Connector = (Socks5Connector) actual;
|
||||
Assert.AreSame(_socketFactoryMock.Object, socks5Connector.SocketFactory);
|
||||
|
||||
_connectionInfoMock.Verify(p => p.ProxyType, Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ProxyType_Undefined()
|
||||
{
|
||||
_connectionInfoMock.Setup(p => p.ProxyType).Returns((ProxyTypes) 666);
|
||||
|
||||
try
|
||||
{
|
||||
_serviceFactory.CreateConnector(_connectionInfoMock.Object, _socketFactoryMock.Object);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (NotSupportedException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("ProxyTypes '666' is not supported.", ex.Message);
|
||||
}
|
||||
|
||||
_connectionInfoMock.Verify(p => p.ProxyType, Times.Once);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,286 +11,6 @@ namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
public partial class SessionTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void ConnectShouldThrowProxyExceptionWhenHttpProxyResponseDoesNotContainStatusLine()
|
||||
{
|
||||
var proxyEndPoint = new IPEndPoint(IPAddress.Loopback, 8123);
|
||||
var serverEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
|
||||
|
||||
using (var proxyStub = new HttpProxyStub(proxyEndPoint))
|
||||
{
|
||||
proxyStub.Responses.Add(Encoding.ASCII.GetBytes("Whatever\r\n"));
|
||||
proxyStub.Start();
|
||||
|
||||
var connectionInfo = CreateConnectionInfoWithHttpProxy(proxyEndPoint, serverEndPoint, "anon");
|
||||
|
||||
using (var session = new Session(connectionInfo, _serviceFactoryMock.Object))
|
||||
{
|
||||
_serviceFactoryMock.Setup(p => p.CreateConnector(connectionInfo))
|
||||
.Returns(_connectorMock.Object);
|
||||
_connectorMock.Setup(p => p.Connect(connectionInfo))
|
||||
.Returns<IConnectionInfo>(c => new HttpConnector().Connect(c));
|
||||
|
||||
try
|
||||
{
|
||||
session.Connect();
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ProxyException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("HTTP response does not contain status line.", ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldThrowProxyExceptionWhenHttpProxyReturnsHttpStatusOtherThan200()
|
||||
{
|
||||
var proxyEndPoint = new IPEndPoint(IPAddress.Loopback, 8123);
|
||||
var serverEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
|
||||
|
||||
using (var proxyStub = new HttpProxyStub(proxyEndPoint))
|
||||
{
|
||||
proxyStub.Responses.Add(Encoding.ASCII.GetBytes("HTTP/1.0 501 Custom\r\n"));
|
||||
proxyStub.Start();
|
||||
|
||||
var connectionInfo = CreateConnectionInfoWithHttpProxy(proxyEndPoint, serverEndPoint, "anon");
|
||||
|
||||
using (var session = new Session(connectionInfo, _serviceFactoryMock.Object))
|
||||
{
|
||||
_serviceFactoryMock.Setup(p => p.CreateConnector(connectionInfo))
|
||||
.Returns(_connectorMock.Object);
|
||||
_connectorMock.Setup(p => p.Connect(connectionInfo))
|
||||
.Returns<IConnectionInfo>(c => new HttpConnector().Connect(c));
|
||||
|
||||
try
|
||||
{
|
||||
session.Connect();
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ProxyException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("HTTP: Status code 501, \"Custom\"", ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldSkipHeadersWhenHttpProxyReturnsHttpStatus200()
|
||||
{
|
||||
var proxyEndPoint = new IPEndPoint(IPAddress.Loopback, 8123);
|
||||
var serverEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
|
||||
|
||||
using (var proxyStub = new HttpProxyStub(proxyEndPoint))
|
||||
{
|
||||
proxyStub.Responses.Add(Encoding.ASCII.GetBytes("HTTP/1.0 200 OK\r\n"));
|
||||
proxyStub.Responses.Add(Encoding.ASCII.GetBytes("Content-Type: application/octet-stream\r\n"));
|
||||
proxyStub.Responses.Add(Encoding.ASCII.GetBytes("\r\n"));
|
||||
proxyStub.Responses.Add(Encoding.ASCII.GetBytes("SSH-666-SshStub"));
|
||||
proxyStub.Start();
|
||||
|
||||
var connectionInfo = CreateConnectionInfoWithHttpProxy(proxyEndPoint, serverEndPoint, "anon");
|
||||
|
||||
using (var session = new Session(connectionInfo, _serviceFactoryMock.Object))
|
||||
{
|
||||
_serviceFactoryMock.Setup(p => p.CreateConnector(connectionInfo))
|
||||
.Returns(_connectorMock.Object);
|
||||
_connectorMock.Setup(p => p.Connect(connectionInfo))
|
||||
.Returns<IConnectionInfo>(c => new HttpConnector().Connect(c));
|
||||
|
||||
try
|
||||
{
|
||||
session.Connect();
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshConnectionException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("Server version '666' is not supported.", ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldSkipContentWhenHttpProxyReturnsHttpStatus200()
|
||||
{
|
||||
var proxyEndPoint = new IPEndPoint(IPAddress.Loopback, 8123);
|
||||
var serverEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
|
||||
|
||||
using (var proxyStub = new HttpProxyStub(proxyEndPoint))
|
||||
{
|
||||
proxyStub.Responses.Add(Encoding.ASCII.GetBytes("HTTP/1.0 200 OK\r\n"));
|
||||
proxyStub.Responses.Add(Encoding.ASCII.GetBytes("Content-Length: 13\r\n"));
|
||||
proxyStub.Responses.Add(Encoding.ASCII.GetBytes("Content-Type: application/octet-stream\r\n"));
|
||||
proxyStub.Responses.Add(Encoding.ASCII.GetBytes("\r\n"));
|
||||
proxyStub.Responses.Add(Encoding.ASCII.GetBytes("DUMMY_CONTENT"));
|
||||
proxyStub.Responses.Add(Encoding.ASCII.GetBytes("SSH-666-SshStub"));
|
||||
proxyStub.Start();
|
||||
|
||||
var connectionInfo = CreateConnectionInfoWithHttpProxy(proxyEndPoint, serverEndPoint, "anon");
|
||||
|
||||
using (var session = new Session(connectionInfo, _serviceFactoryMock.Object))
|
||||
{
|
||||
_serviceFactoryMock.Setup(p => p.CreateConnector(connectionInfo))
|
||||
.Returns(_connectorMock.Object);
|
||||
_connectorMock.Setup(p => p.Connect(connectionInfo))
|
||||
.Returns<IConnectionInfo>(c => new HttpConnector().Connect(c));
|
||||
|
||||
try
|
||||
{
|
||||
session.Connect();
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshConnectionException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("Server version '666' is not supported.", ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldWriteConnectMethodToHttpProxy()
|
||||
{
|
||||
var proxyEndPoint = new IPEndPoint(IPAddress.Loopback, 8123);
|
||||
var serverEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
|
||||
|
||||
using (var proxyStub = new HttpProxyStub(proxyEndPoint))
|
||||
{
|
||||
proxyStub.Responses.Add(Encoding.ASCII.GetBytes("HTTP/1.0 501 Custom\r\n"));
|
||||
proxyStub.Start();
|
||||
|
||||
var connectionInfo = CreateConnectionInfoWithHttpProxy(proxyEndPoint, serverEndPoint, "anon");
|
||||
|
||||
using (var session = new Session(connectionInfo, _serviceFactoryMock.Object))
|
||||
{
|
||||
_serviceFactoryMock.Setup(p => p.CreateConnector(connectionInfo))
|
||||
.Returns(_connectorMock.Object);
|
||||
_connectorMock.Setup(p => p.Connect(connectionInfo))
|
||||
.Returns<IConnectionInfo>(c => new HttpConnector().Connect(c));
|
||||
|
||||
try
|
||||
{
|
||||
session.Connect();
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ProxyException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
Assert.AreEqual(string.Format("CONNECT {0} HTTP/1.0", serverEndPoint), proxyStub.HttpRequest.RequestLine);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldWriteProxyAuthorizationToHttpProxyWhenProxyUserNameIsNotNullAndNotEmpty()
|
||||
{
|
||||
var proxyEndPoint = new IPEndPoint(IPAddress.Loopback, 8123);
|
||||
var serverEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
|
||||
|
||||
using (var proxyStub = new HttpProxyStub(proxyEndPoint))
|
||||
{
|
||||
proxyStub.Responses.Add(Encoding.ASCII.GetBytes("HTTP/1.0 501 Custom\r\n"));
|
||||
proxyStub.Start();
|
||||
|
||||
var connectionInfo = CreateConnectionInfoWithHttpProxy(proxyEndPoint, serverEndPoint, "anon");
|
||||
|
||||
using (var session = new Session(connectionInfo, _serviceFactoryMock.Object))
|
||||
{
|
||||
_serviceFactoryMock.Setup(p => p.CreateConnector(connectionInfo))
|
||||
.Returns(_connectorMock.Object);
|
||||
_connectorMock.Setup(p => p.Connect(connectionInfo))
|
||||
.Returns<IConnectionInfo>(c => new HttpConnector().Connect(c));
|
||||
|
||||
try
|
||||
{
|
||||
session.Connect();
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ProxyException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
var expectedProxyAuthorizationHeader = CreateProxyAuthorizationHeader(connectionInfo);
|
||||
Assert.IsNotNull(proxyStub.HttpRequest.Headers.SingleOrDefault(p => p == expectedProxyAuthorizationHeader));
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldNotWriteProxyAuthorizationToHttpProxyWhenProxyUserNameIsEmpty()
|
||||
{
|
||||
var proxyEndPoint = new IPEndPoint(IPAddress.Loopback, 8123);
|
||||
var serverEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
|
||||
|
||||
using (var proxyStub = new HttpProxyStub(proxyEndPoint))
|
||||
{
|
||||
proxyStub.Responses.Add(Encoding.ASCII.GetBytes("HTTP/1.0 501 Custom\r\n"));
|
||||
proxyStub.Start();
|
||||
|
||||
var connectionInfo = CreateConnectionInfoWithHttpProxy(proxyEndPoint, serverEndPoint, string.Empty);
|
||||
|
||||
using (var session = new Session(connectionInfo, _serviceFactoryMock.Object))
|
||||
{
|
||||
_serviceFactoryMock.Setup(p => p.CreateConnector(connectionInfo))
|
||||
.Returns(_connectorMock.Object);
|
||||
_connectorMock.Setup(p => p.Connect(connectionInfo))
|
||||
.Returns<IConnectionInfo>(c => new HttpConnector().Connect(c));
|
||||
|
||||
try
|
||||
{
|
||||
session.Connect();
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ProxyException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
Assert.IsFalse(proxyStub.HttpRequest.Headers.Any(p => p.StartsWith("Proxy-Authorization:")));
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldNotWriteProxyAuthorizationToHttpProxyWhenProxyUserNameIsNull()
|
||||
{
|
||||
var proxyEndPoint = new IPEndPoint(IPAddress.Loopback, 8123);
|
||||
var serverEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
|
||||
|
||||
using (var proxyStub = new HttpProxyStub(proxyEndPoint))
|
||||
{
|
||||
proxyStub.Responses.Add(Encoding.ASCII.GetBytes("HTTP/1.0 501 Custom\r\n"));
|
||||
proxyStub.Start();
|
||||
|
||||
var connectionInfo = CreateConnectionInfoWithHttpProxy(proxyEndPoint, serverEndPoint, null);
|
||||
using (var session = new Session(connectionInfo, _serviceFactoryMock.Object))
|
||||
{
|
||||
_serviceFactoryMock.Setup(p => p.CreateConnector(connectionInfo))
|
||||
.Returns(_connectorMock.Object);
|
||||
_connectorMock.Setup(p => p.Connect(connectionInfo))
|
||||
.Returns<IConnectionInfo>(c => new HttpConnector().Connect(c));
|
||||
|
||||
try
|
||||
{
|
||||
session.Connect();
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ProxyException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
Assert.IsFalse(proxyStub.HttpRequest.Headers.Any(p => p.StartsWith("Proxy-Authorization:")));
|
||||
}
|
||||
}
|
||||
|
||||
private static ConnectionInfo CreateConnectionInfoWithHttpProxy(IPEndPoint proxyEndPoint, IPEndPoint serverEndPoint, string proxyUserName)
|
||||
{
|
||||
return new ConnectionInfo(
|
||||
|
||||
@@ -1,16 +1,9 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Connection;
|
||||
using Renci.SshNet.Messages.Transport;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
using Renci.SshNet.Tests.Properties;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
@@ -21,25 +14,28 @@ namespace Renci.SshNet.Tests.Classes
|
||||
public partial class SessionTest : TestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISocketFactory> _socketFactoryMock;
|
||||
private Mock<IConnector> _connectorMock;
|
||||
private Mock<IProtocolVersionExchange> _protocolVersionExchangeMock;
|
||||
|
||||
protected override void OnInit()
|
||||
{
|
||||
base.OnInit();
|
||||
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_socketFactoryMock = new Mock<ISocketFactory>(MockBehavior.Strict);
|
||||
_connectorMock = new Mock<IConnector>(MockBehavior.Strict);
|
||||
_protocolVersionExchangeMock = new Mock<IProtocolVersionExchange>(MockBehavior.Strict);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConstructorShouldThrowArgumentNullExceptionWhenConnectionInfoIsNull()
|
||||
{
|
||||
ConnectionInfo connectionInfo = null;
|
||||
var serviceFactory = new Mock<IServiceFactory>(MockBehavior.Strict).Object;
|
||||
const ConnectionInfo connectionInfo = null;
|
||||
|
||||
try
|
||||
{
|
||||
new Session(connectionInfo, serviceFactory);
|
||||
new Session(connectionInfo, _serviceFactoryMock.Object, _socketFactoryMock.Object);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ArgumentNullException ex)
|
||||
@@ -58,7 +54,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
|
||||
try
|
||||
{
|
||||
new Session(connectionInfo, serviceFactory);
|
||||
new Session(connectionInfo, serviceFactory, _socketFactoryMock.Object);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ArgumentNullException ex)
|
||||
@@ -69,400 +65,24 @@ namespace Renci.SshNet.Tests.Classes
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldSkipLinesBeforeProtocolIdentificationString()
|
||||
public void ConstructorShouldThrowArgumentNullExceptionWhenSocketFactoryIsNull()
|
||||
{
|
||||
var serverEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
|
||||
var connectionInfo = CreateConnectionInfo(serverEndPoint, TimeSpan.FromSeconds(5));
|
||||
|
||||
using (var serverStub = new AsyncSocketListener(serverEndPoint))
|
||||
{
|
||||
serverStub.Connected += socket =>
|
||||
{
|
||||
socket.Send(Encoding.ASCII.GetBytes("\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("WELCOME banner\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("SSH-666-SshStub\r\n"));
|
||||
socket.Shutdown(SocketShutdown.Send);
|
||||
};
|
||||
serverStub.Start();
|
||||
|
||||
using (var session = new Session(connectionInfo, _serviceFactoryMock.Object))
|
||||
{
|
||||
_serviceFactoryMock.Setup(p => p.CreateConnector(connectionInfo))
|
||||
.Returns(_connectorMock.Object);
|
||||
_connectorMock.Setup(p => p.Connect(connectionInfo))
|
||||
.Returns<IConnectionInfo>(c => new DirectConnector().Connect(c));
|
||||
|
||||
try
|
||||
{
|
||||
session.Connect();
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshConnectionException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("Server version '666' is not supported.", ex.Message);
|
||||
|
||||
Assert.AreEqual("SSH-666-SshStub", connectionInfo.ServerVersion);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldImmediatelySendIdentificationStringWhenConnectionHasBeenEstablised()
|
||||
{
|
||||
var serverEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
|
||||
var connectionInfo = CreateConnectionInfo(serverEndPoint, TimeSpan.FromSeconds(5));
|
||||
|
||||
using (var serverStub = new AsyncSocketListener(serverEndPoint))
|
||||
{
|
||||
serverStub.Connected += socket =>
|
||||
{
|
||||
var identificationBytes = new byte[2048];
|
||||
var bytesReceived = socket.Receive(identificationBytes);
|
||||
|
||||
if (bytesReceived > 0)
|
||||
{
|
||||
var identificationSttring = Encoding.ASCII.GetString(identificationBytes, 0, bytesReceived);
|
||||
Console.WriteLine("STRING=" + identificationSttring);
|
||||
Console.WriteLine("DONE");
|
||||
|
||||
socket.Send(Encoding.ASCII.GetBytes("\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("WELCOME banner\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("SSH-666-SshStub\r\n"));
|
||||
}
|
||||
|
||||
socket.Shutdown(SocketShutdown.Send);
|
||||
};
|
||||
serverStub.Start();
|
||||
|
||||
using (var session = new Session(connectionInfo, _serviceFactoryMock.Object))
|
||||
{
|
||||
_serviceFactoryMock.Setup(p => p.CreateConnector(connectionInfo))
|
||||
.Returns(_connectorMock.Object);
|
||||
_connectorMock.Setup(p => p.Connect(connectionInfo))
|
||||
.Returns<IConnectionInfo>(c => new DirectConnector().Connect(c));
|
||||
|
||||
try
|
||||
{
|
||||
session.Connect();
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshConnectionException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("Server version '666' is not supported.", ex.Message);
|
||||
|
||||
Assert.AreEqual("SSH-666-SshStub", connectionInfo.ServerVersion);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldSupportProtocolIdentificationStringThatDoesNotEndWithCrlf()
|
||||
{
|
||||
var serverEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
|
||||
var connectionInfo = CreateConnectionInfo(serverEndPoint, TimeSpan.FromSeconds(5));
|
||||
|
||||
using (var serverStub = new AsyncSocketListener(serverEndPoint))
|
||||
{
|
||||
serverStub.Connected += socket =>
|
||||
{
|
||||
socket.Send(Encoding.ASCII.GetBytes("\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("WELCOME banner\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("SSH-666-SshStub"));
|
||||
socket.Shutdown(SocketShutdown.Send);
|
||||
};
|
||||
serverStub.Start();
|
||||
|
||||
using (var session = new Session(connectionInfo, _serviceFactoryMock.Object))
|
||||
{
|
||||
_serviceFactoryMock.Setup(p => p.CreateConnector(connectionInfo))
|
||||
.Returns(_connectorMock.Object);
|
||||
_connectorMock.Setup(p => p.Connect(connectionInfo))
|
||||
.Returns<IConnectionInfo>(c => new DirectConnector().Connect(c));
|
||||
|
||||
try
|
||||
{
|
||||
session.Connect();
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshConnectionException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("Server version '666' is not supported.", ex.Message);
|
||||
|
||||
Assert.AreEqual("SSH-666-SshStub", connectionInfo.ServerVersion);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldThrowSshOperationExceptionWhenServerDoesNotRespondWithinConnectionTimeout()
|
||||
{
|
||||
var serverEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
|
||||
var timeout = TimeSpan.FromMilliseconds(500);
|
||||
Socket clientSocket = null;
|
||||
|
||||
using (var serverStub = new AsyncSocketListener(serverEndPoint))
|
||||
{
|
||||
serverStub.Connected += socket =>
|
||||
{
|
||||
socket.Send(Encoding.ASCII.GetBytes("\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("WELCOME banner\r\n"));
|
||||
clientSocket = socket;
|
||||
};
|
||||
serverStub.Start();
|
||||
|
||||
var connectionInfo = CreateConnectionInfo(serverEndPoint, TimeSpan.FromMilliseconds(500));
|
||||
|
||||
using (var session = new Session(connectionInfo, _serviceFactoryMock.Object))
|
||||
{
|
||||
_serviceFactoryMock.Setup(p => p.CreateConnector(connectionInfo))
|
||||
.Returns(_connectorMock.Object);
|
||||
_connectorMock.Setup(p => p.Connect(connectionInfo))
|
||||
.Returns<IConnectionInfo>(c => new DirectConnector().Connect(c));
|
||||
|
||||
try
|
||||
{
|
||||
session.Connect();
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshOperationTimeoutException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual(string.Format(CultureInfo.InvariantCulture, "Socket read operation has timed out after {0:F0} milliseconds.", timeout.TotalMilliseconds), ex.Message);
|
||||
|
||||
Assert.IsNotNull(clientSocket);
|
||||
Assert.IsTrue(clientSocket.Connected);
|
||||
|
||||
// shut down socket
|
||||
clientSocket.Shutdown(SocketShutdown.Send);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectShouldSshConnectionExceptionWhenServerResponseDoesNotContainProtocolIdentificationString()
|
||||
{
|
||||
var serverEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
|
||||
|
||||
// response ends with CRLF
|
||||
using (var serverStub = new AsyncSocketListener(serverEndPoint))
|
||||
{
|
||||
serverStub.Connected += socket =>
|
||||
{
|
||||
socket.Send(Encoding.ASCII.GetBytes("\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("WELCOME banner\r\n"));
|
||||
socket.Shutdown(SocketShutdown.Send);
|
||||
};
|
||||
serverStub.Start();
|
||||
|
||||
var connectionInfo = CreateConnectionInfo(serverEndPoint, TimeSpan.FromSeconds(5));
|
||||
|
||||
using (var session = new Session(connectionInfo, _serviceFactoryMock.Object))
|
||||
{
|
||||
_serviceFactoryMock.Setup(p => p.CreateConnector(connectionInfo))
|
||||
.Returns(_connectorMock.Object);
|
||||
_connectorMock.Setup(p => p.Connect(connectionInfo))
|
||||
.Returns<IConnectionInfo>(c => new DirectConnector().Connect(c));
|
||||
|
||||
try
|
||||
{
|
||||
session.Connect();
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshConnectionException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("Server response does not contain SSH protocol identification.", ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// response does not end with CRLF
|
||||
using (var serverStub = new AsyncSocketListener(serverEndPoint))
|
||||
{
|
||||
serverStub.Connected += socket =>
|
||||
{
|
||||
socket.Send(Encoding.ASCII.GetBytes("\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("WELCOME banner"));
|
||||
socket.Shutdown(SocketShutdown.Send);
|
||||
};
|
||||
serverStub.Start();
|
||||
|
||||
var connectionInfo = CreateConnectionInfo(serverEndPoint, TimeSpan.FromSeconds(5));
|
||||
|
||||
using (var session = new Session(connectionInfo, _serviceFactoryMock.Object))
|
||||
{
|
||||
_serviceFactoryMock.Setup(p => p.CreateConnector(connectionInfo))
|
||||
.Returns(_connectorMock.Object);
|
||||
_connectorMock.Setup(p => p.Connect(connectionInfo))
|
||||
.Returns<IConnectionInfo>(c => new DirectConnector().Connect(c));
|
||||
|
||||
try
|
||||
{
|
||||
session.Connect();
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshConnectionException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("Server response does not contain SSH protocol identification.", ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// last line is empty
|
||||
using (var serverStub = new AsyncSocketListener(serverEndPoint))
|
||||
{
|
||||
serverStub.Connected += socket =>
|
||||
{
|
||||
socket.Send(Encoding.ASCII.GetBytes("\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("WELCOME banner\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("\r\n"));
|
||||
socket.Shutdown(SocketShutdown.Send);
|
||||
};
|
||||
serverStub.Start();
|
||||
|
||||
var connectionInfo = CreateConnectionInfo(serverEndPoint, TimeSpan.FromSeconds(5));
|
||||
|
||||
using (var session = new Session(connectionInfo, _serviceFactoryMock.Object))
|
||||
{
|
||||
_serviceFactoryMock.Setup(p => p.CreateConnector(connectionInfo))
|
||||
.Returns(_connectorMock.Object);
|
||||
_connectorMock.Setup(p => p.Connect(connectionInfo))
|
||||
.Returns<IConnectionInfo>(c => new DirectConnector().Connect(c));
|
||||
|
||||
try
|
||||
{
|
||||
session.Connect();
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshConnectionException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("Server response does not contain SSH protocol identification.", ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Connect_HostNameInvalid_ShouldThrowSocketExceptionWithErrorCodeHostNotFound()
|
||||
{
|
||||
var connectionInfo = new ConnectionInfo("invalid.", 40, "user",
|
||||
new KeyboardInteractiveAuthenticationMethod("user"));
|
||||
var session = new Session(connectionInfo, _serviceFactoryMock.Object);
|
||||
|
||||
_serviceFactoryMock.Setup(p => p.CreateConnector(connectionInfo))
|
||||
.Returns(_connectorMock.Object);
|
||||
_connectorMock.Setup(p => p.Connect(connectionInfo))
|
||||
.Returns<IConnectionInfo>(c => new DirectConnector().Connect(c));
|
||||
const ISocketFactory socketFactory = null;
|
||||
|
||||
try
|
||||
{
|
||||
session.Connect();
|
||||
new Session(connectionInfo, _serviceFactoryMock.Object, socketFactory);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SocketException ex)
|
||||
catch (ArgumentNullException ex)
|
||||
{
|
||||
Assert.AreEqual(ex.ErrorCode, (int)SocketError.HostNotFound);
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("socketFactory", ex.ParamName);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Connect_ProxyHostNameInvalid_ShouldThrowSocketExceptionWithErrorCodeHostNotFound()
|
||||
{
|
||||
var connectionInfo = new ConnectionInfo("localhost", 40, "user", ProxyTypes.Http, "invalid.", 80,
|
||||
"proxyUser", "proxyPwd", new KeyboardInteractiveAuthenticationMethod("user"));
|
||||
var session = new Session(connectionInfo, _serviceFactoryMock.Object);
|
||||
|
||||
_serviceFactoryMock.Setup(p => p.CreateConnector(connectionInfo))
|
||||
.Returns(_connectorMock.Object);
|
||||
_connectorMock.Setup(p => p.Connect(connectionInfo))
|
||||
.Returns<IConnectionInfo>(c => new HttpConnector().Connect(c));
|
||||
|
||||
try
|
||||
{
|
||||
session.Connect();
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
Assert.AreEqual(ex.ErrorCode, (int)SocketError.HostNotFound);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DisconnectShouldNotThrowExceptionWhenSocketIsNotConnected()
|
||||
{
|
||||
var connectionInfo = new ConnectionInfo("localhost", 6767, Resources.USERNAME,
|
||||
new KeyboardInteractiveAuthenticationMethod(Resources.USERNAME));
|
||||
var session = new Session(connectionInfo, _serviceFactoryMock.Object);
|
||||
|
||||
_serviceFactoryMock.Setup(p => p.CreateConnector(connectionInfo))
|
||||
.Returns(_connectorMock.Object);
|
||||
_connectorMock.Setup(p => p.Connect(connectionInfo))
|
||||
.Returns<IConnectionInfo>(c => new DirectConnector().Connect(c));
|
||||
|
||||
try
|
||||
{
|
||||
session.Connect();
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SocketException)
|
||||
{
|
||||
session.Disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DisconnectShouldNotThrowExceptionWhenConnectHasNotBeenInvoked()
|
||||
{
|
||||
var connectionInfo = new ConnectionInfo("localhost", 6767, Resources.USERNAME,
|
||||
new KeyboardInteractiveAuthenticationMethod(Resources.USERNAME));
|
||||
var session = new Session(connectionInfo, _serviceFactoryMock.Object);
|
||||
|
||||
session.Disconnect();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DisposeShouldNotThrowExceptionWhenSocketIsNotConnected()
|
||||
{
|
||||
var connectionInfo = new ConnectionInfo("localhost", 6767, Resources.USERNAME,
|
||||
new KeyboardInteractiveAuthenticationMethod(Resources.USERNAME));
|
||||
var session = new Session(connectionInfo, _serviceFactoryMock.Object);
|
||||
|
||||
_serviceFactoryMock.Setup(p => p.CreateConnector(connectionInfo))
|
||||
.Returns(_connectorMock.Object);
|
||||
_connectorMock.Setup(p => p.Connect(connectionInfo))
|
||||
.Returns<IConnectionInfo>(c => new DirectConnector().Connect(c));
|
||||
|
||||
try
|
||||
{
|
||||
session.Connect();
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SocketException)
|
||||
{
|
||||
session.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DisposeShouldNotThrowExceptionWhenConenectHasNotBeenInvoked()
|
||||
{
|
||||
var connectionInfo = new ConnectionInfo("localhost", 6767, Resources.USERNAME,
|
||||
new KeyboardInteractiveAuthenticationMethod(Resources.USERNAME));
|
||||
var session = new Session(connectionInfo, _serviceFactoryMock.Object);
|
||||
|
||||
session.Disconnect();
|
||||
}
|
||||
|
||||
private static ConnectionInfo CreateConnectionInfo(IPEndPoint serverEndPoint, TimeSpan timeout)
|
||||
{
|
||||
var connectionInfo = new ConnectionInfo(
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
using Moq;
|
||||
using Renci.SshNet.Connection;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
public abstract class SessionTestBase : TripleATestBase
|
||||
{
|
||||
internal Mock<IServiceFactory> _serviceFactoryMock { get; private set; }
|
||||
internal Mock<ISocketFactory> _socketFactoryMock { get; private set; }
|
||||
internal Mock<IConnector> _connectorMock { get; private set; }
|
||||
|
||||
protected virtual void CreateMocks()
|
||||
{
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_socketFactoryMock = new Mock<ISocketFactory>(MockBehavior.Strict);
|
||||
_connectorMock = new Mock<IConnector>(MockBehavior.Strict);
|
||||
}
|
||||
|
||||
protected virtual void SetupData()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void SetupMocks()
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Arrange()
|
||||
{
|
||||
CreateMocks();
|
||||
SetupData();
|
||||
SetupMocks();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,265 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Messages.Transport;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class SessionTest_ConnectToServerFails : SessionTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private Session _session;
|
||||
private SshConnectionException _connectException;
|
||||
private SshConnectionException _actualException;
|
||||
|
||||
protected override void SetupData()
|
||||
{
|
||||
base.SetupData();
|
||||
|
||||
var serverEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
|
||||
_connectionInfo = CreateConnectionInfo(serverEndPoint, TimeSpan.FromSeconds(5));
|
||||
_session = new Session(_connectionInfo, _serviceFactoryMock.Object, _socketFactoryMock.Object);
|
||||
_connectException = new SshConnectionException();
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
base.SetupMocks();
|
||||
|
||||
_serviceFactoryMock.Setup(p => p.CreateConnector(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_connectorMock.Object);
|
||||
_connectorMock.Setup(p => p.Connect(_connectionInfo))
|
||||
.Throws(_connectException);
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
try
|
||||
{
|
||||
_session.Connect();
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshConnectionException ex)
|
||||
{
|
||||
_actualException = ex;
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientVersionIsRenciSshNet()
|
||||
{
|
||||
Assert.AreEqual("SSH-2.0-Renci.SshNet.SshClient.0.0.1", _session.ClientVersion);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectionInfoShouldReturnConnectionInfoPassedThroughConstructor()
|
||||
{
|
||||
Assert.AreSame(_connectionInfo, _session.ConnectionInfo);
|
||||
}
|
||||
|
||||
public void ConnectShouldHaveRethrownException()
|
||||
{
|
||||
Assert.IsNotNull(_actualException);
|
||||
Assert.AreSame(_connectException, _actualException);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DisconnectShouldNotThrowAnException()
|
||||
{
|
||||
_session.Disconnect();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DisposeShouldNotThrowException()
|
||||
{
|
||||
_session.Dispose();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IsConnectedShouldReturnFalse()
|
||||
{
|
||||
Assert.IsFalse(_session.IsConnected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SendMessageShouldThrowShhConnectionException()
|
||||
{
|
||||
try
|
||||
{
|
||||
_session.SendMessage(new IgnoreMessage());
|
||||
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 SessionIdShouldReturnNull()
|
||||
{
|
||||
Assert.IsNull(_session.SessionId);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ServerVersionShouldReturnNull()
|
||||
{
|
||||
Assert.IsNull(_session.ServerVersion);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void WaitOnHandle_WaitOnHandle_WaitHandle_ShouldThrowArgumentNullExceptionWhenWaitHandleIsNull()
|
||||
{
|
||||
const WaitHandle waitHandle = null;
|
||||
|
||||
try
|
||||
{
|
||||
_session.WaitOnHandle(waitHandle);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ArgumentNullException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("waitHandle", ex.ParamName);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void WaitOnHandle_WaitOnHandle_WaitHandleAndTimeout_ShouldThrowArgumentNullExceptionWhenWaitHandleIsNull()
|
||||
{
|
||||
const WaitHandle waitHandle = null;
|
||||
var timeout = TimeSpan.FromMinutes(5);
|
||||
|
||||
try
|
||||
{
|
||||
_session.WaitOnHandle(waitHandle, timeout);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ArgumentNullException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("waitHandle", ex.ParamName);
|
||||
}
|
||||
}
|
||||
|
||||
[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;
|
||||
Assert.AreSame(_connectionInfo, session.ConnectionInfo);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ISession_MessageListenerCompletedShouldBeSignaled()
|
||||
{
|
||||
var session = (ISession)_session;
|
||||
|
||||
Assert.IsNotNull(session.MessageListenerCompleted);
|
||||
Assert.IsTrue(session.MessageListenerCompleted.WaitOne(0));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ISession_SendMessageShouldThrowShhConnectionException()
|
||||
{
|
||||
var session = (ISession)_session;
|
||||
|
||||
try
|
||||
{
|
||||
session.SendMessage(new IgnoreMessage());
|
||||
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_TrySendMessageShouldReturnFalse()
|
||||
{
|
||||
var session = (ISession)_session;
|
||||
|
||||
var actual = session.TrySendMessage(new IgnoreMessage());
|
||||
|
||||
Assert.IsFalse(actual);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ISession_WaitOnHandle_WaitHandle_ShouldThrowArgumentNullExceptionWhenWaitHandleIsNull()
|
||||
{
|
||||
const WaitHandle waitHandle = null;
|
||||
var session = (ISession)_session;
|
||||
|
||||
try
|
||||
{
|
||||
session.WaitOnHandle(waitHandle);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ArgumentNullException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("waitHandle", ex.ParamName);
|
||||
}
|
||||
}
|
||||
|
||||
[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(
|
||||
serverEndPoint.Address.ToString(),
|
||||
serverEndPoint.Port,
|
||||
"eric",
|
||||
new NoneAuthenticationMethod("eric"));
|
||||
connectionInfo.Timeout = timeout;
|
||||
return connectionInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,7 +66,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
public void ServerVersionShouldNotReturnNull()
|
||||
{
|
||||
Assert.IsNotNull(Session.ServerVersion);
|
||||
Assert.AreEqual("SSH-2.0-SshStub", Session.ServerVersion);
|
||||
Assert.AreEqual("SSH-2.0-OurServerStub", Session.ServerVersion);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
@@ -253,10 +253,17 @@ namespace Renci.SshNet.Tests.Classes
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldBeConnected()
|
||||
{
|
||||
Assert.IsNotNull(ClientSocket);
|
||||
Assert.IsTrue(ClientSocket.Connected);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateConnectorOnServiceFactoryShouldHaveBeenInvokedOnce()
|
||||
{
|
||||
ServiceFactoryMock.Verify(p => p.CreateConnector(ConnectionInfo), Times.Once());
|
||||
ServiceFactoryMock.Verify(p => p.CreateConnector(ConnectionInfo, SocketFactoryMock.Object), Times.Once());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
@@ -22,11 +22,16 @@ namespace Renci.SshNet.Tests.Classes
|
||||
public abstract class SessionTest_ConnectedBase
|
||||
{
|
||||
internal Mock<IServiceFactory> ServiceFactoryMock { get; private set; }
|
||||
internal Mock<ISocketFactory> SocketFactoryMock { get; private set; }
|
||||
internal Mock<IConnector> ConnectorMock { get; private set; }
|
||||
|
||||
private Mock<IProtocolVersionExchange> _protocolVersionExchangeMock;
|
||||
private Mock<IKeyExchange> _keyExchangeMock;
|
||||
private Mock<IClientAuthentication> _clientAuthenticationMock;
|
||||
private IPEndPoint _serverEndPoint;
|
||||
private string _keyExchangeAlgorithm;
|
||||
private bool _authenticationStarted;
|
||||
private SocketFactory _socketFactory;
|
||||
|
||||
protected Random Random { get; private set; }
|
||||
protected byte[] SessionId { get; private set; }
|
||||
@@ -39,6 +44,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
protected Session Session { get; private set; }
|
||||
protected Socket ClientSocket { get; private set; }
|
||||
protected Socket ServerSocket { get; private set; }
|
||||
internal SshIdentification ServerIdentification { get; private set; }
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
@@ -67,6 +73,12 @@ namespace Renci.SshNet.Tests.Classes
|
||||
Session.Dispose();
|
||||
Session = null;
|
||||
}
|
||||
|
||||
if (ClientSocket != null && ClientSocket.Connected)
|
||||
{
|
||||
ClientSocket.Shutdown(SocketShutdown.Both);
|
||||
ClientSocket.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void SetupData()
|
||||
@@ -87,8 +99,11 @@ namespace Renci.SshNet.Tests.Classes
|
||||
DisconnectReceivedRegister = new List<MessageEventArgs<DisconnectMessage>>();
|
||||
ErrorOccurredRegister = new List<ExceptionEventArgs>();
|
||||
ServerBytesReceivedRegister = new List<byte[]>();
|
||||
ServerIdentification = new SshIdentification("2.0", "OurServerStub");
|
||||
_authenticationStarted = false;
|
||||
_socketFactory = new SocketFactory();
|
||||
|
||||
Session = new Session(ConnectionInfo, ServiceFactoryMock.Object);
|
||||
Session = new Session(ConnectionInfo, ServiceFactoryMock.Object, SocketFactoryMock.Object);
|
||||
Session.Disconnected += (sender, args) => DisconnectedRegister.Add(args);
|
||||
Session.DisconnectReceived += (sender, args) => DisconnectReceivedRegister.Add(args);
|
||||
Session.ErrorOccured += (sender, args) => ErrorOccurredRegister.Add(args);
|
||||
@@ -105,60 +120,64 @@ namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
ServerSocket = socket;
|
||||
|
||||
socket.Send(Encoding.ASCII.GetBytes("\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("WELCOME banner\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("SSH-2.0-SshStub\r\n"));
|
||||
// Since we're mocking the protocol version exchange, we'll immediately stat KEX upon
|
||||
// having established the connection instead of when the client has been identified
|
||||
|
||||
var keyExchangeInitMessage = new KeyExchangeInitMessage
|
||||
{
|
||||
CompressionAlgorithmsClientToServer = new string[0],
|
||||
CompressionAlgorithmsServerToClient = new string[0],
|
||||
EncryptionAlgorithmsClientToServer = new string[0],
|
||||
EncryptionAlgorithmsServerToClient = new string[0],
|
||||
KeyExchangeAlgorithms = new[] { _keyExchangeAlgorithm },
|
||||
LanguagesClientToServer = new string[0],
|
||||
LanguagesServerToClient = new string[0],
|
||||
MacAlgorithmsClientToServer = new string[0],
|
||||
MacAlgorithmsServerToClient = new string[0],
|
||||
ServerHostKeyAlgorithms = new string[0]
|
||||
};
|
||||
var keyExchangeInit = keyExchangeInitMessage.GetPacket(8, null);
|
||||
ServerSocket.Send(keyExchangeInit, 4, keyExchangeInit.Length - 4, SocketFlags.None);
|
||||
};
|
||||
|
||||
var counter = 0;
|
||||
|
||||
ServerListener.BytesReceived += (received, socket) =>
|
||||
{
|
||||
ServerBytesReceivedRegister.Add(received);
|
||||
|
||||
switch (counter++)
|
||||
if (!_authenticationStarted)
|
||||
{
|
||||
case 0:
|
||||
var keyExchangeInitMessage = new KeyExchangeInitMessage
|
||||
{
|
||||
CompressionAlgorithmsClientToServer = new string[0],
|
||||
CompressionAlgorithmsServerToClient = new string[0],
|
||||
EncryptionAlgorithmsClientToServer = new string[0],
|
||||
EncryptionAlgorithmsServerToClient = new string[0],
|
||||
KeyExchangeAlgorithms = new[] {_keyExchangeAlgorithm},
|
||||
LanguagesClientToServer = new string[0],
|
||||
LanguagesServerToClient = new string[0],
|
||||
MacAlgorithmsClientToServer = new string[0],
|
||||
MacAlgorithmsServerToClient = new string[0],
|
||||
ServerHostKeyAlgorithms = new string[0]
|
||||
};
|
||||
var keyExchangeInit = keyExchangeInitMessage.GetPacket(8, null);
|
||||
ServerSocket.Send(keyExchangeInit, 4, keyExchangeInit.Length - 4, SocketFlags.None);
|
||||
break;
|
||||
case 1:
|
||||
var serviceAcceptMessage =
|
||||
ServiceAcceptMessageBuilder.Create(ServiceName.UserAuthentication)
|
||||
.Build();
|
||||
ServerSocket.Send(serviceAcceptMessage, 0, serviceAcceptMessage.Length, SocketFlags.None);
|
||||
break;
|
||||
var serviceAcceptMessage = ServiceAcceptMessageBuilder.Create(ServiceName.UserAuthentication)
|
||||
.Build();
|
||||
ServerSocket.Send(serviceAcceptMessage, 0, serviceAcceptMessage.Length, SocketFlags.None);
|
||||
|
||||
_authenticationStarted = true;
|
||||
}
|
||||
};
|
||||
ServerListener.Start();
|
||||
|
||||
ClientSocket = new DirectConnector(_socketFactory).Connect(ConnectionInfo);
|
||||
}
|
||||
|
||||
private void CreateMocks()
|
||||
{
|
||||
ServiceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
SocketFactoryMock = new Mock<ISocketFactory>(MockBehavior.Strict);
|
||||
ConnectorMock = new Mock<IConnector>(MockBehavior.Strict);
|
||||
_protocolVersionExchangeMock = new Mock<IProtocolVersionExchange>(MockBehavior.Strict);
|
||||
_keyExchangeMock = new Mock<IKeyExchange>(MockBehavior.Strict);
|
||||
_clientAuthenticationMock = new Mock<IClientAuthentication>(MockBehavior.Strict);
|
||||
}
|
||||
|
||||
private void SetupMocks()
|
||||
{
|
||||
ServiceFactoryMock.Setup(p => p.CreateConnector(ConnectionInfo))
|
||||
.Returns(ConnectorMock.Object);
|
||||
ServiceFactoryMock.Setup(p => p.CreateConnector(ConnectionInfo, SocketFactoryMock.Object))
|
||||
.Returns(ConnectorMock.Object);
|
||||
ConnectorMock.Setup(p => p.Connect(ConnectionInfo))
|
||||
.Returns<IConnectionInfo>(c => new DirectConnector().Connect(c));
|
||||
.Returns(ClientSocket);
|
||||
ServiceFactoryMock.Setup(p => p.CreateProtocolVersionExchange())
|
||||
.Returns(_protocolVersionExchangeMock.Object);
|
||||
_protocolVersionExchangeMock.Setup(p => p.Start(Session.ClientVersion, ClientSocket, ConnectionInfo.Timeout))
|
||||
.Returns(ServerIdentification);
|
||||
|
||||
ServiceFactoryMock.Setup(
|
||||
p =>
|
||||
p.CreateKeyExchange(ConnectionInfo.KeyExchangeAlgorithms, new[] { _keyExchangeAlgorithm })).Returns(_keyExchangeMock.Object);
|
||||
@@ -184,7 +203,6 @@ namespace Renci.SshNet.Tests.Classes
|
||||
SetupData();
|
||||
SetupMocks();
|
||||
|
||||
ServerListener.Start();
|
||||
Session.Connect();
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Threading;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Messages.Transport;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
@@ -49,7 +50,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
[TestMethod]
|
||||
public void ErrorOccurredIsNeverRaised()
|
||||
{
|
||||
Assert.AreEqual(0, ErrorOccurredRegister.Count);
|
||||
Assert.AreEqual(0, ErrorOccurredRegister.Count, ErrorOccurredRegister.AsString());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
@@ -188,5 +189,12 @@ namespace Renci.SshNet.Tests.Classes
|
||||
Assert.AreEqual(WaitResult.Disconnected, result);
|
||||
Assert.IsNull(exception);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ClientSocketShouldNotBeConnected()
|
||||
{
|
||||
Assert.IsNotNull(ClientSocket);
|
||||
Assert.IsFalse(ClientSocket.Connected);
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -2,6 +2,7 @@
|
||||
using System.Text;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Renci.SshNet.Messages.Connection;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
@@ -33,7 +34,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
[TestMethod]
|
||||
public void ErrorOccurredShouldNotBeRaised()
|
||||
{
|
||||
Assert.AreEqual(0, ErrorOccurredRegister.Count);
|
||||
Assert.AreEqual(0, ErrorOccurredRegister.Count, ErrorOccurredRegister.AsString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+63
-45
@@ -22,12 +22,16 @@ namespace Renci.SshNet.Tests.Classes
|
||||
public class SessionTest_Connected_ServerAndClientDisconnectRace
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISocketFactory> _socketFactoryMock;
|
||||
private Mock<IConnector> _connectorMock;
|
||||
private Mock<IProtocolVersionExchange> _protocolVersionExchangeMock;
|
||||
private Mock<IKeyExchange> _keyExchangeMock;
|
||||
private Mock<IClientAuthentication> _clientAuthenticationMock;
|
||||
private IPEndPoint _serverEndPoint;
|
||||
private string _keyExchangeAlgorithm;
|
||||
private DisconnectMessage _disconnectMessage;
|
||||
private SocketFactory _socketFactory;
|
||||
private bool _authenticationStarted;
|
||||
|
||||
protected Random Random { get; private set; }
|
||||
protected byte[] SessionId { get; private set; }
|
||||
@@ -38,7 +42,9 @@ namespace Renci.SshNet.Tests.Classes
|
||||
protected AsyncSocketListener ServerListener { get; private set; }
|
||||
protected IList<byte[]> ServerBytesReceivedRegister { get; private set; }
|
||||
protected Session Session { get; private set; }
|
||||
protected Socket ClientSocket { get; private set; }
|
||||
protected Socket ServerSocket { get; private set; }
|
||||
internal SshIdentification ServerIdentification { get; private set; }
|
||||
|
||||
private void TearDown()
|
||||
{
|
||||
@@ -51,6 +57,12 @@ namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
Session.Dispose();
|
||||
}
|
||||
|
||||
if (ClientSocket != null && ClientSocket.Connected)
|
||||
{
|
||||
ClientSocket.Shutdown(SocketShutdown.Both);
|
||||
ClientSocket.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void SetupData()
|
||||
@@ -71,76 +83,83 @@ namespace Renci.SshNet.Tests.Classes
|
||||
DisconnectReceivedRegister = new List<MessageEventArgs<DisconnectMessage>>();
|
||||
ErrorOccurredRegister = new List<ExceptionEventArgs>();
|
||||
ServerBytesReceivedRegister = new List<byte[]>();
|
||||
ServerIdentification = new SshIdentification("2.0", "OurServerStub");
|
||||
_authenticationStarted = false;
|
||||
_disconnectMessage = new DisconnectMessage(DisconnectReason.ServiceNotAvailable, "Not today!");
|
||||
_socketFactory = new SocketFactory();
|
||||
|
||||
Session = new Session(ConnectionInfo, _serviceFactoryMock.Object);
|
||||
Session = new Session(ConnectionInfo, _serviceFactoryMock.Object, _socketFactoryMock.Object);
|
||||
Session.Disconnected += (sender, args) => DisconnectedRegister.Add(args);
|
||||
Session.DisconnectReceived += (sender, args) => DisconnectReceivedRegister.Add(args);
|
||||
Session.ErrorOccured += (sender, args) => ErrorOccurredRegister.Add(args);
|
||||
Session.KeyExchangeInitReceived += (sender, args) =>
|
||||
{
|
||||
var newKeysMessage = new NewKeysMessage();
|
||||
var newKeys = newKeysMessage.GetPacket(8, null);
|
||||
ServerSocket.Send(newKeys, 4, newKeys.Length - 4, SocketFlags.None);
|
||||
};
|
||||
{
|
||||
var newKeysMessage = new NewKeysMessage();
|
||||
var newKeys = newKeysMessage.GetPacket(8, null);
|
||||
ServerSocket.Send(newKeys, 4, newKeys.Length - 4, SocketFlags.None);
|
||||
};
|
||||
|
||||
ServerListener = new AsyncSocketListener(_serverEndPoint);
|
||||
ServerListener.Connected += socket =>
|
||||
{
|
||||
ServerSocket = socket;
|
||||
|
||||
socket.Send(Encoding.ASCII.GetBytes("\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("WELCOME banner\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("SSH-2.0-SshStub\r\n"));
|
||||
};
|
||||
|
||||
var counter = 0;
|
||||
|
||||
ServerListener.BytesReceived += (received, socket) =>
|
||||
{
|
||||
ServerBytesReceivedRegister.Add(received);
|
||||
|
||||
switch (counter++)
|
||||
{
|
||||
case 0:
|
||||
var keyExchangeInitMessage = new KeyExchangeInitMessage
|
||||
{
|
||||
CompressionAlgorithmsClientToServer = new string[0],
|
||||
CompressionAlgorithmsServerToClient = new string[0],
|
||||
EncryptionAlgorithmsClientToServer = new string[0],
|
||||
EncryptionAlgorithmsServerToClient = new string[0],
|
||||
KeyExchangeAlgorithms = new[] { _keyExchangeAlgorithm },
|
||||
LanguagesClientToServer = new string[0],
|
||||
LanguagesServerToClient = new string[0],
|
||||
MacAlgorithmsClientToServer = new string[0],
|
||||
MacAlgorithmsServerToClient = new string[0],
|
||||
ServerHostKeyAlgorithms = new string[0]
|
||||
};
|
||||
var keyExchangeInit = keyExchangeInitMessage.GetPacket(8, null);
|
||||
ServerSocket.Send(keyExchangeInit, 4, keyExchangeInit.Length - 4, SocketFlags.None);
|
||||
break;
|
||||
case 1:
|
||||
ServerSocket = socket;
|
||||
|
||||
// Since we're mocking the protocol version exchange, we'll immediately stat KEX upon
|
||||
// having established the connection instead of when the client has been identified
|
||||
|
||||
var keyExchangeInitMessage = new KeyExchangeInitMessage
|
||||
{
|
||||
CompressionAlgorithmsClientToServer = new string[0],
|
||||
CompressionAlgorithmsServerToClient = new string[0],
|
||||
EncryptionAlgorithmsClientToServer = new string[0],
|
||||
EncryptionAlgorithmsServerToClient = new string[0],
|
||||
KeyExchangeAlgorithms = new[] { _keyExchangeAlgorithm },
|
||||
LanguagesClientToServer = new string[0],
|
||||
LanguagesServerToClient = new string[0],
|
||||
MacAlgorithmsClientToServer = new string[0],
|
||||
MacAlgorithmsServerToClient = new string[0],
|
||||
ServerHostKeyAlgorithms = new string[0]
|
||||
};
|
||||
var keyExchangeInit = keyExchangeInitMessage.GetPacket(8, null);
|
||||
ServerSocket.Send(keyExchangeInit, 4, keyExchangeInit.Length - 4, SocketFlags.None);
|
||||
};
|
||||
ServerListener.BytesReceived += (received, socket) =>
|
||||
{
|
||||
ServerBytesReceivedRegister.Add(received);
|
||||
|
||||
if (!_authenticationStarted)
|
||||
{
|
||||
var serviceAcceptMessage =ServiceAcceptMessageBuilder.Create(ServiceName.UserAuthentication).Build();
|
||||
ServerSocket.Send(serviceAcceptMessage, 0, serviceAcceptMessage.Length, SocketFlags.None);
|
||||
break;
|
||||
}
|
||||
};
|
||||
_authenticationStarted = true;
|
||||
}
|
||||
};
|
||||
|
||||
ServerListener.Start();
|
||||
|
||||
ClientSocket = new DirectConnector(_socketFactory).Connect(ConnectionInfo);
|
||||
}
|
||||
|
||||
private void CreateMocks()
|
||||
{
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_socketFactoryMock = new Mock<ISocketFactory>(MockBehavior.Strict);
|
||||
_connectorMock = new Mock<IConnector>(MockBehavior.Strict);
|
||||
_protocolVersionExchangeMock = new Mock<IProtocolVersionExchange>(MockBehavior.Strict);
|
||||
_keyExchangeMock = new Mock<IKeyExchange>(MockBehavior.Strict);
|
||||
_clientAuthenticationMock = new Mock<IClientAuthentication>(MockBehavior.Strict);
|
||||
}
|
||||
|
||||
private void SetupMocks()
|
||||
{
|
||||
_serviceFactoryMock.Setup(p => p.CreateConnector(ConnectionInfo))
|
||||
_serviceFactoryMock.Setup(p => p.CreateConnector(ConnectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_connectorMock.Object);
|
||||
_connectorMock.Setup(p => p.Connect(ConnectionInfo))
|
||||
.Returns<IConnectionInfo>(c => new DirectConnector().Connect(c));
|
||||
.Returns(ClientSocket);
|
||||
_serviceFactoryMock.Setup(p => p.CreateProtocolVersionExchange())
|
||||
.Returns(_protocolVersionExchangeMock.Object);
|
||||
_protocolVersionExchangeMock.Setup(p => p.Start(Session.ClientVersion, ClientSocket, ConnectionInfo.Timeout))
|
||||
.Returns(ServerIdentification);
|
||||
_serviceFactoryMock.Setup(
|
||||
p =>
|
||||
p.CreateKeyExchange(ConnectionInfo.KeyExchangeAlgorithms, new[] { _keyExchangeAlgorithm })).Returns(_keyExchangeMock.Object);
|
||||
@@ -164,7 +183,6 @@ namespace Renci.SshNet.Tests.Classes
|
||||
SetupData();
|
||||
SetupMocks();
|
||||
|
||||
ServerListener.Start();
|
||||
Session.Connect();
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -6,6 +6,7 @@ using System.Threading;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Messages.Transport;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
@@ -70,7 +71,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
[TestMethod]
|
||||
public void ErrorOccurredIsNeverRaised()
|
||||
{
|
||||
Assert.AreEqual(0, ErrorOccurredRegister.Count);
|
||||
Assert.AreEqual(0, ErrorOccurredRegister.Count, ErrorOccurredRegister.AsString());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
+2
-1
@@ -6,6 +6,7 @@ using System.Threading;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Messages.Transport;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
@@ -73,7 +74,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
[TestMethod]
|
||||
public void ErrorOccurredIsNeverRaised()
|
||||
{
|
||||
Assert.AreEqual(0, ErrorOccurredRegister.Count);
|
||||
Assert.AreEqual(0, ErrorOccurredRegister.Count, ErrorOccurredRegister.AsString());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
+2
-1
@@ -5,6 +5,7 @@ using System.Threading;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Messages.Transport;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
@@ -66,7 +67,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
[TestMethod]
|
||||
public void ErrorOccurredIsRaisedOnce()
|
||||
{
|
||||
Assert.AreEqual(1, ErrorOccurredRegister.Count);
|
||||
Assert.AreEqual(1, ErrorOccurredRegister.Count, ErrorOccurredRegister.AsString());
|
||||
|
||||
var errorOccurred = ErrorOccurredRegister[0];
|
||||
Assert.IsNotNull(errorOccurred);
|
||||
|
||||
@@ -4,34 +4,27 @@ using System.Threading;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Connection;
|
||||
using Renci.SshNet.Messages.Transport;
|
||||
using Renci.SshNet.Tests.Common;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class SessionTest_NotConnected
|
||||
public class SessionTest_NotConnected : SessionTestBase
|
||||
{
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private IServiceFactory _serviceFactory;
|
||||
private Session _session;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
}
|
||||
|
||||
protected void Arrange()
|
||||
protected override void SetupData()
|
||||
{
|
||||
var serverEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
|
||||
_connectionInfo = CreateConnectionInfo(serverEndPoint, TimeSpan.FromSeconds(5));
|
||||
_serviceFactory = new Mock<IServiceFactory>(MockBehavior.Strict).Object;
|
||||
}
|
||||
|
||||
protected void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
_session = new Session(_connectionInfo, _serviceFactory);
|
||||
_session = new Session(_connectionInfo, _serviceFactoryMock.Object, _socketFactoryMock.Object);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
@@ -46,6 +39,18 @@ namespace Renci.SshNet.Tests.Classes
|
||||
Assert.AreSame(_connectionInfo, _session.ConnectionInfo);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DisconnectShouldNotThrowException()
|
||||
{
|
||||
_session.Disconnect();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DisposeShouldNotThrowException()
|
||||
{
|
||||
_session.Dispose();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IsConnectedShouldReturnFalse()
|
||||
{
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Common;
|
||||
@@ -15,13 +14,17 @@ namespace Renci.SshNet.Tests.Classes
|
||||
public class SessionTest_SocketConnected_BadPacketAndDispose
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISocketFactory> _socketFactoryMock;
|
||||
private Mock<IConnector> _connectorMock;
|
||||
private Mock<IProtocolVersionExchange> _protocolVersionExchangeMock;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private Session _session;
|
||||
private AsyncSocketListener _serverListener;
|
||||
private IPEndPoint _serverEndPoint;
|
||||
private Socket _serverSocket;
|
||||
private Socket _clientSocket;
|
||||
private SshConnectionException _actualException;
|
||||
private SocketFactory _socketFactory;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
@@ -42,7 +45,9 @@ namespace Renci.SshNet.Tests.Classes
|
||||
protected void CreateMocks()
|
||||
{
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_socketFactoryMock = new Mock<ISocketFactory>(MockBehavior.Strict);
|
||||
_connectorMock = new Mock<IConnector>(MockBehavior.Strict);
|
||||
_protocolVersionExchangeMock = new Mock<IProtocolVersionExchange>(MockBehavior.Strict);
|
||||
}
|
||||
|
||||
protected void SetupData()
|
||||
@@ -55,30 +60,37 @@ namespace Renci.SshNet.Tests.Classes
|
||||
new PasswordAuthenticationMethod("user", "password"));
|
||||
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(200);
|
||||
_actualException = null;
|
||||
_socketFactory = new SocketFactory();
|
||||
|
||||
_serverListener = new AsyncSocketListener(_serverEndPoint);
|
||||
_serverListener.Connected += (socket) =>
|
||||
{
|
||||
_serverSocket = socket;
|
||||
|
||||
socket.Send(Encoding.ASCII.GetBytes("\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("WELCOME banner\r\n"));
|
||||
socket.Send(Encoding.ASCII.GetBytes("SSH-2.0-SshStub\r\n"));
|
||||
};
|
||||
_serverListener.BytesReceived += (received, socket) =>
|
||||
{
|
||||
// Since we're mocking the protocol version exchange, we can immediately send the bad
|
||||
// packet upon establishing the connection
|
||||
|
||||
var badPacket = new byte[] { 0x0a, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05 };
|
||||
_serverSocket.Send(badPacket, 0, badPacket.Length, SocketFlags.None);
|
||||
_serverSocket.Shutdown(SocketShutdown.Send);
|
||||
};
|
||||
_serverListener.Start();
|
||||
|
||||
_session = new Session(_connectionInfo, _serviceFactoryMock.Object, _socketFactoryMock.Object);
|
||||
|
||||
_clientSocket = new DirectConnector(_socketFactory).Connect(_connectionInfo);
|
||||
}
|
||||
|
||||
protected void SetupMocks()
|
||||
{
|
||||
_serviceFactoryMock.Setup(p => p.CreateConnector(_connectionInfo))
|
||||
_serviceFactoryMock.Setup(p => p.CreateConnector(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_connectorMock.Object);
|
||||
_connectorMock.Setup(p => p.Connect(_connectionInfo))
|
||||
.Returns<IConnectionInfo>(c => new DirectConnector().Connect(c));
|
||||
.Returns(_clientSocket);
|
||||
_serviceFactoryMock.Setup(p => p.CreateProtocolVersionExchange())
|
||||
.Returns(_protocolVersionExchangeMock.Object);
|
||||
_protocolVersionExchangeMock.Setup(p => p.Start(_session.ClientVersion, _clientSocket, _connectionInfo.Timeout))
|
||||
.Returns(new SshIdentification("2.0", "XXX"));
|
||||
}
|
||||
|
||||
protected void Arrange()
|
||||
@@ -86,15 +98,13 @@ namespace Renci.SshNet.Tests.Classes
|
||||
CreateMocks();
|
||||
SetupData();
|
||||
SetupMocks();
|
||||
|
||||
_serverListener.Start();
|
||||
}
|
||||
|
||||
protected virtual void Act()
|
||||
{
|
||||
try
|
||||
{
|
||||
using (_session = new Session(_connectionInfo, _serviceFactoryMock.Object))
|
||||
|
||||
{
|
||||
_session.Connect();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
using Moq;
|
||||
using Renci.SshNet.Sftp;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
public abstract class SftpClientTestBase : BaseClientTestBase
|
||||
{
|
||||
internal Mock<ISftpResponseFactory> _sftpResponseFactoryMock { get; private set; }
|
||||
internal Mock<ISftpSession> _sftpSessionMock { get; private set; }
|
||||
|
||||
protected override void CreateMocks()
|
||||
{
|
||||
base.CreateMocks();
|
||||
|
||||
_sftpResponseFactoryMock = new Mock<ISftpResponseFactory>(MockBehavior.Strict);
|
||||
_sftpSessionMock = new Mock<ISftpSession>(MockBehavior.Strict);
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
-33
@@ -4,59 +4,35 @@ using System.Threading;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Connection;
|
||||
using Renci.SshNet.Security;
|
||||
using Renci.SshNet.Sftp;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class SftpClientTest_Connect_SftpSessionConnectFailure
|
||||
public class SftpClientTest_Connect_SftpSessionConnectFailure : SftpClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private Mock<ISftpResponseFactory> _sftpResponseFactoryMock;
|
||||
private Mock<ISftpSession> _sftpSessionMock;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private ApplicationException _sftpSessionConnectionException;
|
||||
private SftpClient _sftpClient;
|
||||
private ApplicationException _actualException;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
}
|
||||
|
||||
private void Arrange()
|
||||
{
|
||||
SetupData();
|
||||
CreateMocks();
|
||||
SetupMocks();
|
||||
|
||||
_sftpClient = new SftpClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
}
|
||||
|
||||
private void SetupData()
|
||||
protected override void SetupData()
|
||||
{
|
||||
_connectionInfo = new ConnectionInfo("host", "user", new NoneAuthenticationMethod("userauth"));
|
||||
_sftpSessionConnectionException = new ApplicationException();
|
||||
}
|
||||
|
||||
private void CreateMocks()
|
||||
{
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
_sftpResponseFactoryMock = new Mock<ISftpResponseFactory>(MockBehavior.Strict);
|
||||
_sftpSessionMock = new Mock<ISftpSession>(MockBehavior.Strict);
|
||||
}
|
||||
|
||||
private void SetupMocks()
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
var sequence = new MockSequence();
|
||||
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence)
|
||||
.Setup(p => p.Connect());
|
||||
@@ -75,7 +51,14 @@ namespace Renci.SshNet.Tests.Classes
|
||||
.Setup(p => p.Dispose());
|
||||
}
|
||||
|
||||
private void Act()
|
||||
protected override void Arrange()
|
||||
{
|
||||
base.Arrange();
|
||||
|
||||
_sftpClient = new SftpClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
}
|
||||
|
||||
protected override void Act()
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -6,44 +6,30 @@ using Renci.SshNet.Sftp;
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class SftpClientTest_Dispose_Connected
|
||||
public class SftpClientTest_Dispose_Connected : SftpClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private Mock<ISftpResponseFactory> _sftpResponseFactoryMock;
|
||||
private Mock<ISftpSession> _sftpSessionMock;
|
||||
private SftpClient _sftpClient;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private int _operationTimeout;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
protected override void SetupData()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
}
|
||||
|
||||
protected void Arrange()
|
||||
{
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
_sftpResponseFactoryMock = new Mock<ISftpResponseFactory>(MockBehavior.Strict);
|
||||
_sftpSessionMock = new Mock<ISftpSession>(MockBehavior.Strict);
|
||||
|
||||
_connectionInfo = new ConnectionInfo("host", "user", new NoneAuthenticationMethod("userauth"));
|
||||
_operationTimeout = new Random().Next(1000, 10000);
|
||||
_sftpClient = new SftpClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
_sftpClient.OperationTimeout = TimeSpan.FromMilliseconds(_operationTimeout);
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
var sequence = new MockSequence();
|
||||
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Returns(_sessionMock.Object);
|
||||
.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSftpResponseFactory())
|
||||
@@ -55,11 +41,16 @@ namespace Renci.SshNet.Tests.Classes
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.OnDisconnecting());
|
||||
_sftpSessionMock.InSequence(sequence).Setup(p => p.Dispose());
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Dispose());
|
||||
}
|
||||
|
||||
protected override void Arrange()
|
||||
{
|
||||
base.Arrange();
|
||||
|
||||
_sftpClient.Connect();
|
||||
}
|
||||
|
||||
protected void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
_sftpClient.Dispose();
|
||||
}
|
||||
@@ -78,10 +69,17 @@ namespace Renci.SshNet.Tests.Classes
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSocketFactoryOnServiceFactoryShouldBeInvokedOnce()
|
||||
{
|
||||
_serviceFactoryMock.Verify(p => p.CreateSocketFactory(), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSessionOnServiceFactoryShouldBeInvokedOnce()
|
||||
{
|
||||
_serviceFactoryMock.Verify(p => p.CreateSession(_connectionInfo), Times.Once);
|
||||
_serviceFactoryMock.Verify(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
@@ -6,40 +6,31 @@ using Renci.SshNet.Sftp;
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class SftpClientTest_Dispose_Disconnected
|
||||
public class SftpClientTest_Dispose_Disconnected : SftpClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private Mock<ISftpResponseFactory> _sftpResponseFactoryMock;
|
||||
private Mock<ISftpSession> _sftpSessionMock;
|
||||
private SftpClient _sftpClient;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
|
||||
private int _operationTimeout;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
protected override void SetupData()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
}
|
||||
|
||||
protected void Arrange()
|
||||
{
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
_sftpResponseFactoryMock = new Mock<ISftpResponseFactory>(MockBehavior.Strict);
|
||||
_sftpSessionMock = new Mock<ISftpSession>(MockBehavior.Strict);
|
||||
|
||||
_connectionInfo = new ConnectionInfo("host", "user", new NoneAuthenticationMethod("userauth"));
|
||||
_operationTimeout = new Random().Next(1000, 10000);
|
||||
_sftpClient = new SftpClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
_sftpClient.OperationTimeout = TimeSpan.FromMilliseconds(_operationTimeout);
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
var sequence = new MockSequence();
|
||||
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Returns(_sessionMock.Object);
|
||||
.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSftpResponseFactory())
|
||||
@@ -51,12 +42,17 @@ namespace Renci.SshNet.Tests.Classes
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.OnDisconnecting());
|
||||
_sftpSessionMock.InSequence(sequence).Setup(p => p.Dispose());
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Dispose());
|
||||
}
|
||||
|
||||
protected override void Arrange()
|
||||
{
|
||||
base.Arrange();
|
||||
|
||||
_sftpClient.Connect();
|
||||
_sftpClient.Disconnect();
|
||||
}
|
||||
|
||||
protected void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
_sftpClient.Dispose();
|
||||
}
|
||||
@@ -75,10 +71,17 @@ namespace Renci.SshNet.Tests.Classes
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSocketFactoryOnServiceFactoryShouldBeInvokedOnce()
|
||||
{
|
||||
_serviceFactoryMock.Verify(p => p.CreateSocketFactory(), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSessionOnServiceFactoryShouldBeInvokedOnce()
|
||||
{
|
||||
_serviceFactoryMock.Verify(p => p.CreateSession(_connectionInfo), Times.Once);
|
||||
_serviceFactoryMock.Verify(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
@@ -6,44 +6,30 @@ using Renci.SshNet.Sftp;
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class SftpClientTest_Dispose_Disposed
|
||||
public class SftpClientTest_Dispose_Disposed : SftpClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private Mock<ISftpResponseFactory> _sftpResponseFactoryMock;
|
||||
private Mock<ISftpSession> _sftpSessionMock;
|
||||
private SftpClient _sftpClient;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private int _operationTimeout;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
protected override void SetupData()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
}
|
||||
|
||||
protected void Arrange()
|
||||
{
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
_sftpResponseFactoryMock = new Mock<ISftpResponseFactory>(MockBehavior.Strict);
|
||||
_sftpSessionMock = new Mock<ISftpSession>(MockBehavior.Strict);
|
||||
|
||||
_connectionInfo = new ConnectionInfo("host", "user", new NoneAuthenticationMethod("userauth"));
|
||||
_operationTimeout = new Random().Next(1000, 10000);
|
||||
_sftpClient = new SftpClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
_sftpClient.OperationTimeout = TimeSpan.FromMilliseconds(_operationTimeout);
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
var sequence = new MockSequence();
|
||||
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Returns(_sessionMock.Object);
|
||||
.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSftpResponseFactory())
|
||||
@@ -55,12 +41,17 @@ namespace Renci.SshNet.Tests.Classes
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.OnDisconnecting());
|
||||
_sftpSessionMock.InSequence(sequence).Setup(p => p.Dispose());
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Dispose());
|
||||
}
|
||||
|
||||
protected override void Arrange()
|
||||
{
|
||||
base.Arrange();
|
||||
|
||||
_sftpClient.Connect();
|
||||
_sftpClient.Dispose();
|
||||
}
|
||||
|
||||
protected void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
_sftpClient.Dispose();
|
||||
}
|
||||
@@ -79,10 +70,17 @@ namespace Renci.SshNet.Tests.Classes
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSocketFactoryOnServiceFactoryShouldBeInvokedOnce()
|
||||
{
|
||||
_serviceFactoryMock.Verify(p => p.CreateSocketFactory(), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSessionOnServiceFactoryShouldBeInvokedOnce()
|
||||
{
|
||||
_serviceFactoryMock.Verify(p => p.CreateSession(_connectionInfo), Times.Once);
|
||||
_serviceFactoryMock.Verify(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
@@ -6,54 +6,49 @@ using Renci.SshNet.Sftp;
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class SftpClientTest_Finalize_Connected
|
||||
public class SftpClientTest_Finalize_Connected : SftpClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private Mock<ISftpResponseFactory> _sftpResponseFactoryMock;
|
||||
private Mock<ISftpSession> _sftpSessionMock;
|
||||
private SftpClient _sftpClient;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private int _operationTimeout;
|
||||
private WeakReference _sftpClientWeakRefence;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
protected override void SetupData()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
}
|
||||
|
||||
protected void Arrange()
|
||||
{
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Loose);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
_sftpResponseFactoryMock = new Mock<ISftpResponseFactory>(MockBehavior.Strict);
|
||||
_sftpSessionMock = new Mock<ISftpSession>(MockBehavior.Strict);
|
||||
|
||||
_connectionInfo = new ConnectionInfo("host", "user", new NoneAuthenticationMethod("userauth"));
|
||||
_operationTimeout = new Random().Next(1000, 10000);
|
||||
_sftpClient = new SftpClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
_sftpClient.OperationTimeout = TimeSpan.FromMilliseconds(_operationTimeout);
|
||||
_sftpClientWeakRefence = new WeakReference(_sftpClient);
|
||||
}
|
||||
|
||||
_serviceFactoryMock.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Returns(_sessionMock.Object);
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
_serviceFactoryMock.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.Setup(p => p.Connect());
|
||||
_serviceFactoryMock.Setup(p => p.CreateSftpResponseFactory())
|
||||
.Returns(_sftpResponseFactoryMock.Object);
|
||||
_serviceFactoryMock.Setup(p => p.CreateSftpSession(_sessionMock.Object, _operationTimeout, _connectionInfo.Encoding, _sftpResponseFactoryMock.Object))
|
||||
.Returns(_sftpSessionMock.Object);
|
||||
_sftpSessionMock.Setup(p => p.Connect());
|
||||
}
|
||||
|
||||
protected override void Arrange()
|
||||
{
|
||||
base.Arrange();
|
||||
|
||||
_sftpClient.Connect();
|
||||
_sftpClient = null;
|
||||
|
||||
// we need to dereference all other mocks as they might otherwise hold the target alive
|
||||
_sessionMock = null;
|
||||
_connectionInfo = null;
|
||||
_serviceFactoryMock = null;
|
||||
// We need to dereference all mocks as they might otherwise hold the target alive
|
||||
//(through recorded invocations?)
|
||||
CreateMocks();
|
||||
}
|
||||
|
||||
protected void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
@@ -62,13 +57,25 @@ namespace Renci.SshNet.Tests.Classes
|
||||
[TestMethod]
|
||||
public void DisconnectOnSftpSessionShouldNeverBeInvoked()
|
||||
{
|
||||
// Since we recreated the mocks, this test has no value
|
||||
// We'll leaving ths test just in case we have a solution that does not require us
|
||||
// to recreate the mocks
|
||||
_sftpSessionMock.Verify(p => p.Disconnect(), Times.Never);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DisposeOnSftpSessionShouldNeverBeInvoked()
|
||||
{
|
||||
// Since we recreated the mocks, this test has no value
|
||||
// We'll leaving ths test just in case we have a solution that does not require us
|
||||
// to recreate the mocks
|
||||
_sftpSessionMock.Verify(p => p.Dispose(), Times.Never);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SftpClientShouldHaveBeenFinalized()
|
||||
{
|
||||
Assert.IsNull(_sftpClientWeakRefence.Target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
-25
@@ -8,11 +8,8 @@ using Renci.SshNet.Common;
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class
|
||||
SshClientTest_CreateShellStream_TerminalNameAndColumnsAndRowsAndWidthAndHeightAndBufferSizeAndTerminalModes_Connected
|
||||
public class SshClientTest_CreateShellStream_TerminalNameAndColumnsAndRowsAndWidthAndHeightAndBufferSizeAndTerminalModes_Connected : BaseClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private SshClient _sshClient;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private string _terminalName;
|
||||
@@ -25,14 +22,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
private ShellStream _expected;
|
||||
private ShellStream _actual;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
}
|
||||
|
||||
private void SetupData()
|
||||
protected override void SetupData()
|
||||
{
|
||||
var random = new Random();
|
||||
|
||||
@@ -49,18 +39,15 @@ namespace Renci.SshNet.Tests.Classes
|
||||
_expected = CreateShellStream();
|
||||
}
|
||||
|
||||
private void CreateMocks()
|
||||
{
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
}
|
||||
|
||||
private void SetupMocks()
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
var sequence = new MockSequence();
|
||||
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence)
|
||||
.Setup(p => p.Connect());
|
||||
@@ -76,17 +63,15 @@ namespace Renci.SshNet.Tests.Classes
|
||||
.Returns(_expected);
|
||||
}
|
||||
|
||||
private void Arrange()
|
||||
protected override void Arrange()
|
||||
{
|
||||
SetupData();
|
||||
CreateMocks();
|
||||
SetupMocks();
|
||||
base.Arrange();
|
||||
|
||||
_sshClient = new SshClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
_sshClient.Connect();
|
||||
}
|
||||
|
||||
protected void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
_actual = _sshClient.CreateShellStream(_terminalName,
|
||||
_widthColumns,
|
||||
|
||||
+10
-24
@@ -8,10 +8,8 @@ using Renci.SshNet.Common;
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class SshClientTest_CreateShellStream_TerminalNameAndColumnsAndRowsAndWidthAndHeightAndBufferSize_Connected
|
||||
public class SshClientTest_CreateShellStream_TerminalNameAndColumnsAndRowsAndWidthAndHeightAndBufferSize_Connected : BaseClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private SshClient _sshClient;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private string _terminalName;
|
||||
@@ -23,14 +21,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
private ShellStream _expected;
|
||||
private ShellStream _actual;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
}
|
||||
|
||||
private void SetupData()
|
||||
protected override void SetupData()
|
||||
{
|
||||
var random = new Random();
|
||||
|
||||
@@ -46,18 +37,15 @@ namespace Renci.SshNet.Tests.Classes
|
||||
_expected = CreateShellStream();
|
||||
}
|
||||
|
||||
private void CreateMocks()
|
||||
{
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
}
|
||||
|
||||
private void SetupMocks()
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
var sequence = new MockSequence();
|
||||
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence)
|
||||
.Setup(p => p.Connect());
|
||||
@@ -73,17 +61,15 @@ namespace Renci.SshNet.Tests.Classes
|
||||
.Returns(_expected);
|
||||
}
|
||||
|
||||
private void Arrange()
|
||||
protected override void Arrange()
|
||||
{
|
||||
SetupData();
|
||||
CreateMocks();
|
||||
SetupMocks();
|
||||
base.Arrange();
|
||||
|
||||
_sshClient = new SshClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
_sshClient.Connect();
|
||||
}
|
||||
|
||||
protected void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
_actual = _sshClient.CreateShellStream(_terminalName,
|
||||
_widthColumns,
|
||||
|
||||
@@ -5,42 +5,37 @@ using Moq;
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class SshClientTest_Disconnect_ForwardedPortStarted
|
||||
public class SshClientTest_Disconnect_ForwardedPortStarted : BaseClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private Mock<ForwardedPort> _forwardedPortMock;
|
||||
private SshClient _sshClient;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
}
|
||||
|
||||
protected void Arrange()
|
||||
protected override void SetupData()
|
||||
{
|
||||
_connectionInfo = new ConnectionInfo("host", "user", new NoneAuthenticationMethod("userauth"));
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
var sequence = new MockSequence();
|
||||
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
_forwardedPortMock = new Mock<ForwardedPort>(MockBehavior.Strict);
|
||||
|
||||
_serviceFactoryMock.InSequence(sequence).Setup(p => p.CreateSession(_connectionInfo)).Returns(_sessionMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
_forwardedPortMock.InSequence(sequence).Setup(p => p.Start());
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.OnDisconnecting());
|
||||
_forwardedPortMock.InSequence(sequence).Setup(p => p.Stop());
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Dispose());
|
||||
}
|
||||
|
||||
protected override void Arrange()
|
||||
{
|
||||
base.Arrange();
|
||||
|
||||
_sshClient = new SshClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
_sshClient.Connect();
|
||||
@@ -49,7 +44,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
_forwardedPortMock.Object.Start();
|
||||
}
|
||||
|
||||
protected void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
_sshClient.Disconnect();
|
||||
}
|
||||
|
||||
@@ -4,51 +4,55 @@ using Moq;
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class SshClientTest_Dispose_Connected
|
||||
public class SshClientTest_Dispose_Connected : BaseClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private SshClient _sshClient;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
}
|
||||
|
||||
protected void Arrange()
|
||||
protected override void SetupData()
|
||||
{
|
||||
_connectionInfo = new ConnectionInfo("host", "user", new NoneAuthenticationMethod("userauth"));
|
||||
}
|
||||
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
var sequence = new MockSequence();
|
||||
_serviceFactoryMock.InSequence(sequence).Setup(p => p.CreateSession(_connectionInfo)).Returns(_sessionMock.Object);
|
||||
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.OnDisconnecting());
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Dispose());
|
||||
}
|
||||
|
||||
protected override void Arrange()
|
||||
{
|
||||
base.Arrange();
|
||||
|
||||
_sshClient = new SshClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
_sshClient.Connect();
|
||||
}
|
||||
|
||||
protected void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
_sshClient.Dispose();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSocketFactoryOnServiceFactoryShouldBeInvokedOnce()
|
||||
{
|
||||
_serviceFactoryMock.Verify(p => p.CreateSocketFactory(), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSessionOnServiceFactoryShouldBeInvokedOnce()
|
||||
{
|
||||
_serviceFactoryMock.Verify(p => p.CreateSession(_connectionInfo), Times.Once);
|
||||
_serviceFactoryMock.Verify(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
@@ -4,52 +4,56 @@ using Moq;
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class SshClientTest_Dispose_Disconnected
|
||||
public class SshClientTest_Dispose_Disconnected : BaseClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private SshClient _sshClient;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
}
|
||||
|
||||
protected void Arrange()
|
||||
protected override void SetupData()
|
||||
{
|
||||
_connectionInfo = new ConnectionInfo("host", "user", new NoneAuthenticationMethod("userauth"));
|
||||
}
|
||||
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
var sequence = new MockSequence();
|
||||
_serviceFactoryMock.InSequence(sequence).Setup(p => p.CreateSession(_connectionInfo)).Returns(_sessionMock.Object);
|
||||
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.OnDisconnecting());
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Dispose());
|
||||
}
|
||||
|
||||
protected override void Arrange()
|
||||
{
|
||||
base.Arrange();
|
||||
|
||||
_sshClient = new SshClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
_sshClient.Connect();
|
||||
_sshClient.Disconnect();
|
||||
}
|
||||
|
||||
protected void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
_sshClient.Dispose();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSocketFactoryOnServiceFactoryShouldBeInvokedOnce()
|
||||
{
|
||||
_serviceFactoryMock.Verify(p => p.CreateSocketFactory(), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSessionOnServiceFactoryShouldBeInvokedOnce()
|
||||
{
|
||||
_serviceFactoryMock.Verify(p => p.CreateSession(_connectionInfo), Times.Once);
|
||||
_serviceFactoryMock.Verify(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
@@ -4,52 +4,56 @@ using Moq;
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class SshClientTest_Dispose_Disposed
|
||||
public class SshClientTest_Dispose_Disposed : BaseClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private SshClient _sshClient;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
}
|
||||
|
||||
protected void Arrange()
|
||||
protected override void SetupData()
|
||||
{
|
||||
_connectionInfo = new ConnectionInfo("host", "user", new NoneAuthenticationMethod("userauth"));
|
||||
}
|
||||
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
var sequence = new MockSequence();
|
||||
_serviceFactoryMock.InSequence(sequence).Setup(p => p.CreateSession(_connectionInfo)).Returns(_sessionMock.Object);
|
||||
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.OnDisconnecting());
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Dispose());
|
||||
}
|
||||
|
||||
protected override void Arrange()
|
||||
{
|
||||
base.Arrange();
|
||||
|
||||
_sshClient = new SshClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
_sshClient.Connect();
|
||||
_sshClient.Dispose();
|
||||
}
|
||||
|
||||
protected void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
_sshClient.Dispose();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSocketFactoryOnServiceFactoryShouldBeInvokedOnce()
|
||||
{
|
||||
_serviceFactoryMock.Verify(p => p.CreateSocketFactory(), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateSessionOnServiceFactoryShouldBeInvokedOnce()
|
||||
{
|
||||
_serviceFactoryMock.Verify(p => p.CreateSession(_connectionInfo), Times.Once);
|
||||
_serviceFactoryMock.Verify(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
@@ -6,42 +6,44 @@ using Moq;
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class SshClientTest_Dispose_ForwardedPortStarted
|
||||
public class SshClientTest_Dispose_ForwardedPortStarted : BaseClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private Mock<ForwardedPort> _forwardedPortMock;
|
||||
private SshClient _sshClient;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
protected override void CreateMocks()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
base.CreateMocks();
|
||||
|
||||
_forwardedPortMock = new Mock<ForwardedPort>(MockBehavior.Strict);
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
}
|
||||
|
||||
protected void Arrange()
|
||||
protected override void SetupData()
|
||||
{
|
||||
_connectionInfo = new ConnectionInfo("host", "user", new NoneAuthenticationMethod("userauth"));
|
||||
}
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
var sequence = new MockSequence();
|
||||
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
_forwardedPortMock = new Mock<ForwardedPort>(MockBehavior.Strict);
|
||||
|
||||
_serviceFactoryMock.InSequence(sequence).Setup(p => p.CreateSession(_connectionInfo)).Returns(_sessionMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSocketFactory())
|
||||
.Returns(_socketFactoryMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo, _socketFactoryMock.Object))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
_forwardedPortMock.InSequence(sequence).Setup(p => p.Start());
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.OnDisconnecting());
|
||||
_forwardedPortMock.InSequence(sequence).Setup(p => p.Stop());
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Dispose());
|
||||
}
|
||||
|
||||
protected override void Arrange()
|
||||
{
|
||||
base.Arrange();
|
||||
|
||||
_sshClient = new SshClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
_sshClient.Connect();
|
||||
@@ -50,7 +52,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
_forwardedPortMock.Object.Start();
|
||||
}
|
||||
|
||||
protected void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
_sshClient.Dispose();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
@@ -12,9 +13,11 @@ namespace Renci.SshNet.Tests.Common
|
||||
{
|
||||
private readonly IPEndPoint _endPoint;
|
||||
private readonly ManualResetEvent _acceptCallbackDone;
|
||||
private List<Socket> _connectedClients;
|
||||
private Socket _listener;
|
||||
private Thread _receiveThread;
|
||||
private bool _started;
|
||||
private object _syncLock;
|
||||
|
||||
public delegate void BytesReceivedHandler(byte[] bytesReceived, Socket socket);
|
||||
public delegate void ConnectedHandler(Socket socket);
|
||||
@@ -27,6 +30,8 @@ namespace Renci.SshNet.Tests.Common
|
||||
{
|
||||
_endPoint = endPoint;
|
||||
_acceptCallbackDone = new ManualResetEvent(false);
|
||||
_connectedClients = new List<Socket>();
|
||||
_syncLock = new object();
|
||||
ShutdownRemoteCommunicationSocket = true;
|
||||
}
|
||||
|
||||
@@ -56,11 +61,31 @@ namespace Renci.SshNet.Tests.Common
|
||||
public void Stop()
|
||||
{
|
||||
_started = false;
|
||||
|
||||
lock (_syncLock)
|
||||
{
|
||||
foreach (var connectedClient in _connectedClients)
|
||||
{
|
||||
try
|
||||
{
|
||||
connectedClient.Shutdown(SocketShutdown.Send);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.Error.WriteLine("[{0}] Failure shutting down socket: {1}",
|
||||
typeof(AsyncSocketListener).FullName,
|
||||
ex);
|
||||
}
|
||||
|
||||
DrainSocket(connectedClient);
|
||||
}
|
||||
}
|
||||
|
||||
if (_listener != null)
|
||||
{
|
||||
_listener.Dispose();
|
||||
_listener = null;
|
||||
}
|
||||
|
||||
if (_receiveThread != null)
|
||||
{
|
||||
_receiveThread.Join();
|
||||
@@ -87,15 +112,23 @@ namespace Renci.SshNet.Tests.Common
|
||||
|
||||
private void AcceptCallback(IAsyncResult ar)
|
||||
{
|
||||
// Signal the main thread to continue.
|
||||
// Signal the main thread to continue
|
||||
_acceptCallbackDone.Set();
|
||||
|
||||
// Get the socket that handles the client request.
|
||||
var listener = (Socket)ar.AsyncState;
|
||||
// Get the socket that listens for inbound connections
|
||||
var listener = (Socket) ar.AsyncState;
|
||||
|
||||
// Get the socket that handles the client request
|
||||
var handler = listener.EndAccept(ar);
|
||||
|
||||
// Signal new connection
|
||||
SignalConnected(handler);
|
||||
|
||||
// Register client socket
|
||||
_connectedClients.Add(handler);
|
||||
|
||||
try
|
||||
{
|
||||
var handler = listener.EndAccept(ar);
|
||||
SignalConnected(handler);
|
||||
var state = new SocketStateObject(handler);
|
||||
handler.BeginReceive(state.Buffer, 0, state.Buffer.Length, 0, ReadCallback, state);
|
||||
}
|
||||
@@ -109,7 +142,7 @@ namespace Renci.SshNet.Tests.Common
|
||||
private void ReadCallback(IAsyncResult ar)
|
||||
{
|
||||
// Retrieve the state object and the handler socket
|
||||
// from the asynchronous state object.
|
||||
// from the asynchronous state object
|
||||
var state = (SocketStateObject) ar.AsyncState;
|
||||
var handler = state.Socket;
|
||||
|
||||
@@ -132,8 +165,6 @@ namespace Renci.SshNet.Tests.Common
|
||||
var bytesReceived = new byte[bytesRead];
|
||||
Array.Copy(state.Buffer, bytesReceived, bytesRead);
|
||||
SignalBytesReceived(bytesReceived, handler);
|
||||
|
||||
// prepare to receive more bytes
|
||||
handler.BeginReceive(state.Buffer, 0, state.Buffer.Length, 0, ReadCallback, state);
|
||||
}
|
||||
else
|
||||
@@ -142,8 +173,13 @@ namespace Renci.SshNet.Tests.Common
|
||||
|
||||
if (ShutdownRemoteCommunicationSocket)
|
||||
{
|
||||
handler.Shutdown(SocketShutdown.Both);
|
||||
handler.Close();
|
||||
lock (_syncLock)
|
||||
{
|
||||
handler.Shutdown(SocketShutdown.Send);
|
||||
handler.Close();
|
||||
|
||||
_connectedClients.Remove(handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -169,6 +205,30 @@ namespace Renci.SshNet.Tests.Common
|
||||
subscribers(client);
|
||||
}
|
||||
|
||||
private static void DrainSocket(Socket socket)
|
||||
{
|
||||
var buffer = new byte[128];
|
||||
|
||||
try
|
||||
{
|
||||
while (true && socket.Connected)
|
||||
{
|
||||
var bytesRead = socket.Receive(buffer);
|
||||
if (bytesRead == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
Console.Error.WriteLine("[{0}] Failure draining socket ({1}): {2}",
|
||||
typeof(AsyncSocketListener).FullName,
|
||||
ex.SocketErrorCode.ToString("G"),
|
||||
ex);
|
||||
}
|
||||
}
|
||||
|
||||
private class SocketStateObject
|
||||
{
|
||||
public Socket Socket { get; private set; }
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Renci.SshNet.Tests.Common
|
||||
{
|
||||
public abstract class TripleATestBase
|
||||
{
|
||||
[TestInitialize]
|
||||
public void Init()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
TearDown();
|
||||
}
|
||||
|
||||
protected virtual void TearDown()
|
||||
{
|
||||
}
|
||||
|
||||
protected abstract void Arrange();
|
||||
|
||||
protected abstract void Act();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -457,7 +457,7 @@ namespace Renci.SshNet
|
||||
|
||||
private ISession CreateAndConnectSession()
|
||||
{
|
||||
var session = _serviceFactory.CreateSession(ConnectionInfo);
|
||||
var session = _serviceFactory.CreateSession(ConnectionInfo, _serviceFactory.CreateSocketFactory());
|
||||
session.HostKeyReceived += Session_HostKeyReceived;
|
||||
session.ErrorOccured += Session_ErrorOccured;
|
||||
|
||||
|
||||
@@ -9,6 +9,16 @@ namespace Renci.SshNet.Connection
|
||||
{
|
||||
internal abstract class ConnectorBase : IConnector
|
||||
{
|
||||
protected ConnectorBase(ISocketFactory socketFactory)
|
||||
{
|
||||
if (socketFactory == null)
|
||||
throw new ArgumentNullException("socketFactory");
|
||||
|
||||
SocketFactory = socketFactory;
|
||||
}
|
||||
|
||||
internal ISocketFactory SocketFactory { get; private set; }
|
||||
|
||||
public abstract Socket Connect(IConnectionInfo connectionInfo);
|
||||
|
||||
/// <summary>
|
||||
@@ -26,18 +36,35 @@ namespace Renci.SshNet.Connection
|
||||
|
||||
DiagnosticAbstraction.Log(string.Format("Initiating connection to '{0}:{1}'.", host, port));
|
||||
|
||||
var socket = SocketAbstraction.Connect(ep, timeout);
|
||||
var socket = SocketFactory.Create(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
const int socketBufferSize = 2 * Session.MaximumSshPacketSize;
|
||||
socket.SendBufferSize = socketBufferSize;
|
||||
socket.ReceiveBufferSize = socketBufferSize;
|
||||
return socket;
|
||||
try
|
||||
{
|
||||
SocketAbstraction.Connect(socket, ep, timeout);
|
||||
|
||||
const int socketBufferSize = 2 * Session.MaximumSshPacketSize;
|
||||
socket.SendBufferSize = socketBufferSize;
|
||||
socket.ReceiveBufferSize = socketBufferSize;
|
||||
return socket;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
socket.Dispose();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
protected static byte SocketReadByte(Socket socket)
|
||||
{
|
||||
var buffer = new byte[1];
|
||||
SocketRead(socket, buffer, 0, 1);
|
||||
SocketRead(socket, buffer, 0, 1, Session.InfiniteTimeSpan);
|
||||
return buffer[0];
|
||||
}
|
||||
|
||||
protected static byte SocketReadByte(Socket socket, TimeSpan readTimeout)
|
||||
{
|
||||
var buffer = new byte[1];
|
||||
SocketRead(socket, buffer, 0, 1, readTimeout);
|
||||
return buffer[0];
|
||||
}
|
||||
|
||||
@@ -52,16 +79,31 @@ namespace Renci.SshNet.Connection
|
||||
/// The number of bytes read.
|
||||
/// </returns>
|
||||
/// <exception cref="SshConnectionException">The socket is closed.</exception>
|
||||
/// <exception cref="SshOperationTimeoutException">The read has timed-out.</exception>
|
||||
/// <exception cref="SocketException">The read failed.</exception>
|
||||
protected static int SocketRead(Socket socket, byte[] buffer, int offset, int length)
|
||||
{
|
||||
var bytesRead = SocketAbstraction.Read(socket, buffer, offset, length, Session.InfiniteTimeSpan);
|
||||
return SocketRead(socket, buffer, offset, length, Session.InfiniteTimeSpan);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a blocking read on the socket until <paramref name="length"/> bytes are received.
|
||||
/// </summary>
|
||||
/// <param name="socket">The <see cref="Socket"/> to read from.</param>
|
||||
/// <param name="buffer">An array of type <see cref="byte"/> that is the storage location for the received data.</param>
|
||||
/// <param name="offset">The position in <paramref name="buffer"/> parameter to store the received data.</param>
|
||||
/// <param name="length">The number of bytes to read.</param>
|
||||
/// <param name="readTimeout">The maximum time to wait until <paramref name="length"/> bytes have been received.</param>
|
||||
/// <returns>
|
||||
/// The number of bytes read.
|
||||
/// </returns>
|
||||
/// <exception cref="SshConnectionException">The socket is closed.</exception>
|
||||
/// <exception cref="SshOperationTimeoutException">The read has timed-out.</exception>
|
||||
/// <exception cref="SocketException">The read failed.</exception>
|
||||
protected static int SocketRead(Socket socket, byte[] buffer, int offset, int length, TimeSpan readTimeout)
|
||||
{
|
||||
var bytesRead = SocketAbstraction.Read(socket, buffer, offset, length, readTimeout);
|
||||
if (bytesRead == 0)
|
||||
{
|
||||
// when we're in the disconnecting state (either triggered by client or server), then the
|
||||
// SshConnectionException will interrupt the message listener loop (if not already interrupted)
|
||||
// and the exception itself will be ignored (in RaiseError)
|
||||
throw new SshConnectionException("An established connection was aborted by the server.",
|
||||
DisconnectReason.ConnectionLost);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,10 @@ namespace Renci.SshNet.Connection
|
||||
{
|
||||
internal class DirectConnector : ConnectorBase
|
||||
{
|
||||
public DirectConnector(ISocketFactory socketFactory) : base(socketFactory)
|
||||
{
|
||||
}
|
||||
|
||||
public override Socket Connect(IConnectionInfo connectionInfo)
|
||||
{
|
||||
return SocketConnect(connectionInfo.Host, connectionInfo.Port, connectionInfo.Timeout);
|
||||
|
||||
@@ -8,18 +8,57 @@ using System.Text.RegularExpressions;
|
||||
|
||||
namespace Renci.SshNet.Connection
|
||||
{
|
||||
/// <summary>
|
||||
/// Establishes a tunnel via an HTTP proxy server.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <list type="table">
|
||||
/// <listheader>
|
||||
/// <term>Specification</term>
|
||||
/// <description>URL</description>
|
||||
/// </listheader>
|
||||
/// <item>
|
||||
/// <term>HTTP CONNECT method</term>
|
||||
/// <description>https://tools.ietf.org/html/rfc7231#section-4.3.6</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>HTTP Authentication: Basic and Digest Access Authentication</term>
|
||||
/// <description>https://tools.ietf.org/html/rfc2617</description>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </remarks>
|
||||
internal class HttpConnector : ConnectorBase
|
||||
{
|
||||
public HttpConnector(ISocketFactory socketFactory) : base(socketFactory)
|
||||
{
|
||||
}
|
||||
|
||||
public override Socket Connect(IConnectionInfo connectionInfo)
|
||||
{
|
||||
var socket = SocketConnect(connectionInfo.ProxyHost, connectionInfo.ProxyPort, connectionInfo.Timeout);
|
||||
|
||||
try
|
||||
{
|
||||
HandleProxyConnect(connectionInfo, socket);
|
||||
return socket;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
socket.Shutdown(SocketShutdown.Both);
|
||||
socket.Dispose();
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleProxyConnect(IConnectionInfo connectionInfo, Socket socket)
|
||||
{
|
||||
var httpResponseRe = new Regex(@"HTTP/(?<version>\d[.]\d) (?<statusCode>\d{3}) (?<reasonPhrase>.+)$");
|
||||
var httpHeaderRe = new Regex(@"(?<fieldName>[^\[\]()<>@,;:\""/?={} \t]+):(?<fieldValue>.+)?");
|
||||
|
||||
SocketAbstraction.Send(socket, SshData.Ascii.GetBytes(string.Format("CONNECT {0}:{1} HTTP/1.0\r\n", connectionInfo.Host, connectionInfo.Port)));
|
||||
|
||||
// Sent proxy authorization is specified
|
||||
// Sent proxy authorization if specified
|
||||
if (!string.IsNullOrEmpty(connectionInfo.ProxyUsername))
|
||||
{
|
||||
var authorization = string.Format("Proxy-Authorization: Basic {0}\r\n",
|
||||
@@ -50,9 +89,9 @@ namespace Renci.SshNet.Connection
|
||||
statusCode = (HttpStatusCode)int.Parse(httpStatusCode);
|
||||
if (statusCode != HttpStatusCode.OK)
|
||||
{
|
||||
var reasonPhrase = statusMatch.Result("${reasonPhrase}");
|
||||
throw new ProxyException(string.Format("HTTP: Status code {0}, \"{1}\"", httpStatusCode,
|
||||
reasonPhrase));
|
||||
throw new ProxyException(string.Format("HTTP: Status code {0}, \"{1}\"",
|
||||
httpStatusCode,
|
||||
statusMatch.Result("${reasonPhrase}")));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +117,7 @@ namespace Renci.SshNet.Connection
|
||||
if (contentLength > 0)
|
||||
{
|
||||
var contentBody = new byte[contentLength];
|
||||
SocketRead(socket, contentBody, 0, contentLength);
|
||||
SocketRead(socket, contentBody, 0, contentLength, connectionInfo.Timeout);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -88,21 +127,19 @@ namespace Renci.SshNet.Connection
|
||||
{
|
||||
throw new ProxyException("HTTP response does not contain status line.");
|
||||
}
|
||||
|
||||
return socket;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a blocking read on the socket until a line is read.
|
||||
/// </summary>
|
||||
/// <param name="socket">The <see cref="Socket"/> to read from.</param>
|
||||
/// <param name="timeout">A <see cref="TimeSpan"/> that represents the time to wait until a line is read.</param>
|
||||
/// <param name="readTimeout">A <see cref="TimeSpan"/> that represents the time to wait until a line is read.</param>
|
||||
/// <exception cref="SshOperationTimeoutException">The read has timed-out.</exception>
|
||||
/// <exception cref="SocketException">An error occurred when trying to access the socket.</exception>
|
||||
/// <returns>
|
||||
/// The line read from the socket, or <c>null</c> when the remote server has shutdown and all data has been received.
|
||||
/// </returns>
|
||||
private static string SocketReadLine(Socket socket, TimeSpan timeout)
|
||||
private static string SocketReadLine(Socket socket, TimeSpan readTimeout)
|
||||
{
|
||||
var encoding = SshData.Ascii;
|
||||
var buffer = new List<byte>();
|
||||
@@ -112,10 +149,12 @@ namespace Renci.SshNet.Connection
|
||||
// to be processed by subsequent invocations
|
||||
do
|
||||
{
|
||||
var bytesRead = SocketAbstraction.Read(socket, data, 0, data.Length, timeout);
|
||||
var bytesRead = SocketAbstraction.Read(socket, data, 0, data.Length, readTimeout);
|
||||
if (bytesRead == 0)
|
||||
{
|
||||
// the remote server shut down the socket
|
||||
break;
|
||||
}
|
||||
|
||||
var b = data[0];
|
||||
buffer.Add(b);
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Renci.SshNet.Connection
|
||||
{
|
||||
internal interface ISocketFactory
|
||||
{
|
||||
Socket Create(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Renci.SshNet.Connection
|
||||
{
|
||||
internal class SocketFactory : ISocketFactory
|
||||
{
|
||||
public Socket Create(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType)
|
||||
{
|
||||
return new Socket(addressFamily, SocketType.Stream, ProtocolType.Tcp) { NoDelay = true };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,26 +2,58 @@
|
||||
using Renci.SshNet.Common;
|
||||
using System;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Connection
|
||||
{
|
||||
/// <summary>
|
||||
/// Establishes a tunnel via a SOCKS4 proxy server.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// https://www.openssh.com/txt/socks4.protocol
|
||||
/// </remarks>
|
||||
internal class Socks4Connector : ConnectorBase
|
||||
{
|
||||
public Socks4Connector(ISocketFactory socketFactory) : base(socketFactory)
|
||||
{
|
||||
}
|
||||
|
||||
public override Socket Connect(IConnectionInfo connectionInfo)
|
||||
{
|
||||
var socket = SocketConnect(connectionInfo.ProxyHost, connectionInfo.ProxyPort, connectionInfo.Timeout);
|
||||
|
||||
try
|
||||
{
|
||||
HandleProxyConnect(connectionInfo, socket);
|
||||
return socket;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
socket.Shutdown(SocketShutdown.Both);
|
||||
socket.Dispose();
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Establishes a connection to the server via a SOCKS5 proxy.
|
||||
/// </summary>
|
||||
/// <param name="connectionInfo">The connection information.</param>
|
||||
/// <param name="socket">The <see cref="Socket"/>.</param>
|
||||
private void HandleProxyConnect(IConnectionInfo connectionInfo, Socket socket)
|
||||
{
|
||||
var connectionRequest = CreateSocks4ConnectionRequest(connectionInfo.Host, (ushort)connectionInfo.Port, connectionInfo.ProxyUsername);
|
||||
SocketAbstraction.Send(socket, connectionRequest);
|
||||
|
||||
// Read null byte
|
||||
if (SocketReadByte(socket) != 0)
|
||||
// Read reply version
|
||||
if (SocketReadByte(socket, connectionInfo.Timeout) != 0x00)
|
||||
{
|
||||
throw new ProxyException("SOCKS4: Null is expected.");
|
||||
}
|
||||
|
||||
// Read response code
|
||||
var code = SocketReadByte(socket);
|
||||
var code = SocketReadByte(socket, connectionInfo.Timeout);
|
||||
|
||||
switch (code)
|
||||
{
|
||||
@@ -37,15 +69,14 @@ namespace Renci.SshNet.Connection
|
||||
throw new ProxyException("SOCKS4: Not valid response.");
|
||||
}
|
||||
|
||||
var dummyBuffer = new byte[6]; // field 3 (2 bytes) and field 4 (4) should be ignored
|
||||
SocketRead(socket, dummyBuffer, 0, 6);
|
||||
|
||||
return socket;
|
||||
var destBuffer = new byte[6]; // destination port and IP address should be ignored
|
||||
SocketRead(socket, destBuffer, 0, destBuffer.Length, connectionInfo.Timeout);
|
||||
}
|
||||
|
||||
private static byte[] CreateSocks4ConnectionRequest(string hostname, ushort port, string username)
|
||||
{
|
||||
var addressBytes = GetSocks4DestinationAddress(hostname);
|
||||
var proxyUserBytes = GetProxyUserBytes(username);
|
||||
|
||||
var connectionRequest = new byte
|
||||
[
|
||||
@@ -58,7 +89,7 @@ namespace Renci.SshNet.Connection
|
||||
// IP address
|
||||
addressBytes.Length +
|
||||
// Username
|
||||
username.Length +
|
||||
proxyUserBytes.Length +
|
||||
// Null terminator
|
||||
1
|
||||
];
|
||||
@@ -79,6 +110,11 @@ namespace Renci.SshNet.Connection
|
||||
Buffer.BlockCopy(addressBytes, 0, connectionRequest, index, addressBytes.Length);
|
||||
index += addressBytes.Length;
|
||||
|
||||
// User name
|
||||
Buffer.BlockCopy(proxyUserBytes, 0, connectionRequest, index, proxyUserBytes.Length);
|
||||
index += proxyUserBytes.Length;
|
||||
|
||||
// Null terminator
|
||||
connectionRequest[index] = 0x00;
|
||||
|
||||
return connectionRequest;
|
||||
@@ -99,5 +135,15 @@ namespace Renci.SshNet.Connection
|
||||
|
||||
throw new ProxyException(string.Format("SOCKS4 only supports IPv4. No such address found for '{0}'.", hostname));
|
||||
}
|
||||
|
||||
private static byte[] GetProxyUserBytes(string proxyUser)
|
||||
{
|
||||
if (proxyUser == null)
|
||||
{
|
||||
return Array<byte>.Empty;
|
||||
}
|
||||
|
||||
return Encoding.ASCII.GetBytes(proxyUser);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,12 +5,43 @@ using System.Net.Sockets;
|
||||
|
||||
namespace Renci.SshNet.Connection
|
||||
{
|
||||
/// <summary>
|
||||
/// Establishes a tunnel via a SOCKS5 proxy server.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// https://en.wikipedia.org/wiki/SOCKS#SOCKS5
|
||||
/// </remarks>
|
||||
internal class Socks5Connector : ConnectorBase
|
||||
{
|
||||
public Socks5Connector(ISocketFactory socketFactory) : base(socketFactory)
|
||||
{
|
||||
}
|
||||
|
||||
public override Socket Connect(IConnectionInfo connectionInfo)
|
||||
{
|
||||
var socket = SocketConnect(connectionInfo.ProxyHost, connectionInfo.ProxyPort, connectionInfo.Timeout);
|
||||
|
||||
try
|
||||
{
|
||||
HandleProxyConnect(connectionInfo, socket);
|
||||
return socket;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
socket.Shutdown(SocketShutdown.Both);
|
||||
socket.Dispose();
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Establishes a connection to the server via a SOCKS5 proxy.
|
||||
/// </summary>
|
||||
/// <param name="connectionInfo">The connection information.</param>
|
||||
/// <param name="socket">The <see cref="Socket"/>.</param>
|
||||
private void HandleProxyConnect(IConnectionInfo connectionInfo, Socket socket)
|
||||
{
|
||||
var greeting = new byte[]
|
||||
{
|
||||
// SOCKS version number
|
||||
@@ -26,7 +57,9 @@ namespace Renci.SshNet.Connection
|
||||
|
||||
var socksVersion = SocketReadByte(socket);
|
||||
if (socksVersion != 0x05)
|
||||
{
|
||||
throw new ProxyException(string.Format("SOCKS Version '{0}' is not supported.", socksVersion));
|
||||
}
|
||||
|
||||
var authenticationMethod = SocketReadByte(socket);
|
||||
switch (authenticationMethod)
|
||||
@@ -50,7 +83,7 @@ namespace Renci.SshNet.Connection
|
||||
throw new ProxyException("SOCKS5: No acceptable authentication methods were offered.");
|
||||
}
|
||||
|
||||
var connectionRequest = CreateSocks5ConnectionRequest(connectionInfo.Host, (ushort)connectionInfo.Port);
|
||||
var connectionRequest = CreateSocks5ConnectionRequest(connectionInfo.Host, (ushort) connectionInfo.Port);
|
||||
SocketAbstraction.Send(socket, connectionRequest);
|
||||
|
||||
// Read Server SOCKS5 version
|
||||
@@ -111,8 +144,6 @@ namespace Renci.SshNet.Connection
|
||||
|
||||
// Read 2 bytes to be ignored
|
||||
SocketRead(socket, port, 0, 2);
|
||||
|
||||
return socket;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -145,14 +176,14 @@ namespace Renci.SshNet.Connection
|
||||
authenticationRequest[index++] = 0x01;
|
||||
|
||||
// Length of the username
|
||||
authenticationRequest[index++] = (byte)username.Length;
|
||||
authenticationRequest[index++] = (byte) username.Length;
|
||||
|
||||
// Username
|
||||
SshData.Ascii.GetBytes(username, 0, username.Length, authenticationRequest, index);
|
||||
index += username.Length;
|
||||
|
||||
// Length of the password
|
||||
authenticationRequest[index++] = (byte)password.Length;
|
||||
authenticationRequest[index++] = (byte) password.Length;
|
||||
|
||||
// Password
|
||||
SshData.Ascii.GetBytes(password, 0, password.Length, authenticationRequest, index);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user