Merge branch 'develop'

This commit is contained in:
drieseng
2020-12-30 22:28:44 +01:00
147 changed files with 10096 additions and 2096 deletions
@@ -1183,6 +1183,9 @@
</Compile>
<Compile Include="..\Renci.SshNet\SftpClient.cs">
<Link>SftpClient.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\ISftpClient.cs">
<Link>ISftpClient.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\Sftp\Flags.cs">
<Link>Sftp\Flags.cs</Link>
@@ -1189,6 +1189,9 @@
</Compile>
<Compile Include="..\Renci.SshNet\SftpClient.cs">
<Link>SftpClient.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\ISftpClient.cs">
<Link>ISftpClient.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\Sftp\Flags.cs">
<Link>Sftp\Flags.cs</Link>
@@ -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();
}
}
}
@@ -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]
@@ -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]
@@ -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]
@@ -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)
{
}
}
}
}
@@ -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]
@@ -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)
@@ -181,4 +181,4 @@ namespace Renci.SshNet.Tests.Classes
PublicKeyAuthenticationMethodMock.Verify(p => p.Authenticate(SessionMock.Object), Times.Exactly(2));
}
}
}
}
@@ -1506,10 +1506,12 @@ namespace Renci.SshNet.Tests.Classes.Common
Assert.AreEqual("0", a.ToString(), "#4");
a = new BigInteger();
#pragma warning disable CS1718 // Comparison made to same variable
Assert.AreEqual(true, a == a, "#5");
a = new BigInteger();
Assert.AreEqual(false, a < a, "#6");
#pragma warning restore CS1718 // Comparison made to same variable
a = new BigInteger();
Assert.AreEqual(true, a < 10L, "#7");
@@ -0,0 +1,155 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Renci.SshNet.Common;
using System;
namespace Renci.SshNet.Tests.Classes.Common
{
[TestClass]
public class PacketDumpTest
{
[TestMethod]
public void Create_ByteArrayAndIndentLevel_DataIsNull()
{
const byte[] data = null;
try
{
PacketDump.Create(data, 0);
Assert.Fail();
}
catch (ArgumentNullException ex)
{
Assert.IsNull(ex.InnerException);
Assert.AreEqual("data", ex.ParamName);
}
}
[TestMethod]
public void Create_ByteArrayAndIndentLevel_IndentLevelLessThanZero()
{
var data = new byte[0];
try
{
PacketDump.Create(data, -1);
Assert.Fail();
}
catch (ArgumentOutOfRangeException ex)
{
Assert.IsNull(ex.InnerException);
Assert.AreEqual(string.Format("Cannot be less than zero.{0}Parameter name: {1}", Environment.NewLine, ex.ParamName), ex.Message);
Assert.AreEqual("indentLevel", ex.ParamName);
}
}
[TestMethod]
public void Create_ByteArrayAndIndentLevel_DataIsEmpty()
{
var data = new byte[0];
var actual = PacketDump.Create(data, 2);
Assert.AreEqual(string.Empty, actual);
}
[TestMethod]
public void Create_ByteArrayAndIndentLevel_DataIsMultipleOfLineWidth_IndentLevelTwo()
{
var data = new byte[]
{
0x07, 0x00, 0x1f, 0x65, 0x20, 0x62, 0x09, 0x44, 0x7f, 0x0d, 0x0a, 0x36, 0x80, 0x53, 0x53, 0x48,
0x2e, 0x4e, 0x45, 0x54, 0x20, 0x32, 0x30, 0x32, 0x30, 0x20, 0xf6, 0x7a, 0x32, 0x7f, 0x1f, 0x7e
};
var expected = " 00000000 07 00 1F 65 20 62 09 44 7F 0D 0A 36 80 53 53 48 ...e b.D...6.SSH" +
Environment.NewLine +
" 00000010 2E 4E 45 54 20 32 30 32 30 20 F6 7A 32 7F 1F 7E .NET 2020 .z2..~";
var actual = PacketDump.Create(data, 2);
Assert.AreEqual(expected, actual);
}
[TestMethod]
public void Create_ByteArrayAndIndentLevel_DataIsMultipleOfLineWidth_IndentLevelZero()
{
var data = new byte[]
{
0x07, 0x00, 0x1f, 0x65, 0x20, 0x62, 0x09, 0x44, 0x7f, 0x0d, 0x0a, 0x36, 0x80, 0x53, 0x53, 0x48,
0x2e, 0x4e, 0x45, 0x54, 0x20, 0x32, 0x30, 0x32, 0x30, 0x20, 0xf6, 0x7a, 0x32, 0x7f, 0x1f, 0x7e
};
var expected = "00000000 07 00 1F 65 20 62 09 44 7F 0D 0A 36 80 53 53 48 ...e b.D...6.SSH" +
Environment.NewLine +
"00000010 2E 4E 45 54 20 32 30 32 30 20 F6 7A 32 7F 1F 7E .NET 2020 .z2..~";
var actual = PacketDump.Create(data, 0);
Assert.AreEqual(expected, actual);
}
[TestMethod]
public void Create_ByteArrayAndIndentLevel_DataIsLineWith()
{
var data = new byte[]
{
0x07, 0x00, 0x1f, 0x65, 0x20, 0x62, 0x09, 0x44, 0x7f, 0x0d, 0x0a, 0x36, 0x80, 0x53, 0x53, 0x48
};
var expected = " 00000000 07 00 1F 65 20 62 09 44 7F 0D 0A 36 80 53 53 48 ...e b.D...6.SSH";
var actual = PacketDump.Create(data, 2);
Assert.AreEqual(expected, actual);
}
[TestMethod]
public void Create_ByteArrayAndIndentLevel_DataIsLessThanLineWith()
{
var data = new byte[]
{
0x07, 0x00, 0x1f, 0x65, 0x20, 0x62, 0x09, 0x44, 0x7f, 0x0d, 0x0a, 0x36, 0x80, 0x53
};
var expected = " 00000000 07 00 1F 65 20 62 09 44 7F 0D 0A 36 80 53 ...e b.D...6.S";
var actual = PacketDump.Create(data, 2);
Assert.AreEqual(expected, actual);
}
[TestMethod]
public void Create_ByteArrayAndIndentLevel_DataIsGreaterThanLineWidthButLessThanMultipleOfLineWidth()
{
var data = new byte[]
{
0x07, 0x00, 0x1f, 0x65, 0x20, 0x62, 0x09, 0x44, 0x7f, 0x0d, 0x0a, 0x36, 0x80, 0x53, 0x53, 0x48,
0x2e, 0x4e, 0x45, 0x54
};
var expected = " 00000000 07 00 1F 65 20 62 09 44 7F 0D 0A 36 80 53 53 48 ...e b.D...6.SSH" +
Environment.NewLine +
" 00000010 2E 4E 45 54 .NET";
var actual = PacketDump.Create(data, 2);
Assert.AreEqual(expected, actual);
}
[TestMethod]
public void Create_ByteArrayAndIndentLevel_DataIsGreaterThanMultipleOfLineWidth()
{
var data = new byte[]
{
0x07, 0x00, 0x1f, 0x65, 0x20, 0x62, 0x09, 0x44, 0x7f, 0x0d, 0x0a, 0x36, 0x80, 0x53, 0x53, 0x48,
0x2e, 0x4e, 0x45, 0x54, 0x20, 0x32, 0x30, 0x32, 0x30, 0x20, 0xf6, 0x7a, 0x32, 0x7f, 0x1f, 0x7e,
0x78, 0x54, 0x00, 0x52
};
var expected = " 00000000 07 00 1F 65 20 62 09 44 7F 0D 0A 36 80 53 53 48 ...e b.D...6.SSH" +
Environment.NewLine +
" 00000010 2E 4E 45 54 20 32 30 32 30 20 F6 7A 32 7F 1F 7E .NET 2020 .z2..~" +
Environment.NewLine +
" 00000020 78 54 00 52 xT.R";
var actual = PacketDump.Create(data, 2);
Assert.AreEqual(expected, actual);
}
}
}
@@ -1,18 +1,18 @@
using System;
using System.Threading;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Renci.SshNet.Common;
using Renci.SshNet.Tests.Common;
namespace Renci.SshNet.Tests.Classes.Common
{
[TestClass]
public class PipeStream_Close_BlockingRead
public class PipeStream_Close_BlockingRead : TripleATestBase
{
private PipeStream _pipeStream;
private int _bytesRead;
private IAsyncResult _asyncReadResult;
private Thread _readThread;
[TestInitialize]
public void Init()
protected override void Arrange()
{
_pipeStream = new PipeStream();
@@ -22,26 +22,25 @@ namespace Renci.SshNet.Tests.Classes.Common
_bytesRead = 123;
Action readAction = () => _bytesRead = _pipeStream.Read(new byte[4], 0, 4);
_asyncReadResult = readAction.BeginInvoke(null, null);
// ensure we've started reading
_asyncReadResult.AsyncWaitHandle.WaitOne(50);
_readThread = new Thread(() => _bytesRead = _pipeStream.Read(new byte[4], 0, 4));
_readThread.Start();
Act();
// ensure we've started reading
Assert.IsFalse(_readThread.Join(50));
}
protected void Act()
protected override void Act()
{
_pipeStream.Close();
// give async read time to complete
_asyncReadResult.AsyncWaitHandle.WaitOne(100);
_readThread.Join(100);
}
[TestMethod]
public void BlockingReadShouldHaveBeenInterrupted()
{
Assert.IsTrue(_asyncReadResult.IsCompleted);
Assert.AreEqual(ThreadState.Stopped, _readThread.ThreadState);
}
[TestMethod]
@@ -1,22 +1,23 @@
using System;
using System.Threading;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Renci.SshNet.Common;
using Renci.SshNet.Tests.Common;
namespace Renci.SshNet.Tests.Classes.Common
{
[TestClass]
public class PipeStream_Close_BlockingWrite
public class PipeStream_Close_BlockingWrite : TripleATestBase
{
private PipeStream _pipeStream;
private Exception _writeException;
private IAsyncResult _asyncWriteResult;
private Thread _writehread;
[TestInitialize]
public void Init()
protected override void Arrange()
{
_pipeStream = new PipeStream {MaxBufferLength = 3};
Action writeAction = () =>
_writehread = new Thread(() =>
{
_pipeStream.WriteByte(10);
_pipeStream.WriteByte(13);
@@ -33,26 +34,25 @@ namespace Renci.SshNet.Tests.Classes.Common
_writeException = ex;
throw;
}
};
_asyncWriteResult = writeAction.BeginInvoke(null, null);
// ensure we've started writing
_asyncWriteResult.AsyncWaitHandle.WaitOne(50);
});
_writehread.Start();
Act();
// ensure we've started writing
Assert.IsFalse(_writehread.Join(50));
}
protected void Act()
protected override void Act()
{
_pipeStream.Close();
// give async write time to complete
_asyncWriteResult.AsyncWaitHandle.WaitOne(100);
// give write time to complete
_writehread.Join(100);
}
[TestMethod]
public void BlockingWriteShouldHaveBeenInterrupted()
{
Assert.IsTrue(_asyncWriteResult.IsCompleted);
Assert.AreEqual(ThreadState.Stopped, _writehread.ThreadState);
}
[TestMethod]
@@ -1,20 +1,19 @@
using System;
using System.Threading;
using System.Threading;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Renci.SshNet.Common;
using Renci.SshNet.Tests.Common;
namespace Renci.SshNet.Tests.Classes.Common
{
[TestClass]
public class PipeStream_Flush_BytesRemainingAfterRead
public class PipeStream_Flush_BytesRemainingAfterRead : TripleATestBase
{
private PipeStream _pipeStream;
private byte[] _readBuffer;
private int _bytesRead;
private IAsyncResult _asyncReadResult;
private Thread _readThread;
[TestInitialize]
public void Init()
protected override void Arrange()
{
_pipeStream = new PipeStream();
_pipeStream.WriteByte(10);
@@ -27,25 +26,25 @@ namespace Renci.SshNet.Tests.Classes.Common
_bytesRead = 0;
_readBuffer = new byte[4];
Action readAction = () => _bytesRead = _pipeStream.Read(_readBuffer, 0, _readBuffer.Length);
_asyncReadResult = readAction.BeginInvoke(null, null);
_asyncReadResult.AsyncWaitHandle.WaitOne(50);
_readThread = new Thread(() => _bytesRead = _pipeStream.Read(_readBuffer, 0, _readBuffer.Length));
_readThread.Start();
Act();
// ensure we've started reading
_readThread.Join(50);
}
protected void Act()
protected override void Act()
{
_pipeStream.Flush();
// give async read time to complete
_asyncReadResult.AsyncWaitHandle.WaitOne(100);
_readThread.Join(100);
}
[TestMethod]
public void AsyncReadShouldHaveFinished()
{
Assert.IsTrue(_asyncReadResult.IsCompleted);
Assert.AreEqual(ThreadState.Stopped, _readThread.ThreadState);
}
[TestMethod]
@@ -1,19 +1,19 @@
using System;
using System.Threading;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Renci.SshNet.Common;
using Renci.SshNet.Tests.Common;
namespace Renci.SshNet.Tests.Classes.Common
{
[TestClass]
public class PipeStream_Flush_NoBytesRemainingAfterRead
public class PipeStream_Flush_NoBytesRemainingAfterRead : TripleATestBase
{
private PipeStream _pipeStream;
private byte[] _readBuffer;
private int _bytesRead;
private IAsyncResult _asyncReadResult;
private Thread _readThread;
[TestInitialize]
public void Init()
protected override void Arrange()
{
_pipeStream = new PipeStream();
_pipeStream.WriteByte(10);
@@ -22,25 +22,25 @@ namespace Renci.SshNet.Tests.Classes.Common
_bytesRead = 0;
_readBuffer = new byte[4];
Action readAction = () => _bytesRead = _pipeStream.Read(_readBuffer, 0, _readBuffer.Length);
_asyncReadResult = readAction.BeginInvoke(null, null);
_asyncReadResult.AsyncWaitHandle.WaitOne(50);
_readThread = new Thread(() => _bytesRead = _pipeStream.Read(_readBuffer, 0, _readBuffer.Length));
_readThread.Start();
Act();
// ensure we've started reading
Assert.IsFalse(_readThread.Join(50));
}
protected void Act()
protected override void Act()
{
_pipeStream.Flush();
// give async read time to complete
_asyncReadResult.AsyncWaitHandle.WaitOne(100);
_readThread.Join(100);
}
[TestMethod]
public void AsyncReadShouldHaveFinished()
{
Assert.IsTrue(_asyncReadResult.IsCompleted);
Assert.AreEqual(ThreadState.Stopped, _readThread.ThreadState);
}
[TestMethod]
@@ -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"));
}
}
}
@@ -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());
}
}
}
@@ -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());
}
}
}
@@ -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);
}
}
}
@@ -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();
}
}
}
@@ -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());
}
}
}
@@ -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());
}
}
}
@@ -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);
}
}
}
@@ -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());
}
}
}
@@ -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());
}
}
}
@@ -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());
}
}
}
@@ -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());
}
}
}
@@ -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());
}
}
}
@@ -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());
}
}
}
@@ -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());
}
}
}
@@ -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_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 (_proxyServer != null)
{
_proxyServer.Dispose();
}
if (_clientSocket != null)
{
_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());
}
}
}
@@ -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());
}
}
}
@@ -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());
}
}
}
@@ -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());
}
}
}
@@ -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());
}
}
}
@@ -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());
}
}
}
@@ -0,0 +1,122 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Renci.SshNet.Common;
using Renci.SshNet.Connection;
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 ProtocolVersionExchangeTest_ConnectionClosedByServer_NoDataSentByServer
{
private AsyncSocketListener _server;
private ProtocolVersionExchange _protocolVersionExchange;
private string _clientVersion;
private TimeSpan _timeout;
private IPEndPoint _serverEndPoint;
private List<byte> _dataReceivedByServer;
private bool _clientDisconnected;
private Socket _client;
private SshConnectionException _actualException;
[TestInitialize]
public void Setup()
{
Arrange();
Act();
}
[TestCleanup]
public void Cleanup()
{
if (_server != null)
{
_server.Dispose();
_server = null;
}
if (_client != null)
{
_client.Shutdown(SocketShutdown.Both);
_client.Close();
_client = null;
}
}
protected void Arrange()
{
_clientVersion = "\uD55C";
_timeout = TimeSpan.FromSeconds(5);
_serverEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
_dataReceivedByServer = new List<byte>();
_server = new AsyncSocketListener(_serverEndPoint);
_server.Start();
_server.BytesReceived += (bytes, socket) =>
{
_dataReceivedByServer.AddRange(bytes);
socket.Shutdown(SocketShutdown.Send);
};
_server.Disconnected += (socket) => _clientDisconnected = true;
_client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_client.Connect(_serverEndPoint);
_protocolVersionExchange = new ProtocolVersionExchange();
}
protected void Act()
{
try
{
_protocolVersionExchange.Start(_clientVersion, _client, _timeout);
Assert.Fail();
}
catch (SshConnectionException ex)
{
_actualException = ex;
}
}
[TestMethod]
public void StartShouldHaveThrownSshConnectionException()
{
Assert.IsNotNull(_actualException);
Assert.IsNull(_actualException.InnerException);
Assert.AreEqual(string.Format("The server response does not contain an SSH identification string.{0}" +
"The connection to the remote server was closed before any data was received.{0}{0}" +
"More information on the Protocol Version Exchange is available here:{0}" +
"https://tools.ietf.org/html/rfc4253#section-4.2",
Environment.NewLine),
_actualException.Message);
}
[TestMethod]
public void ClientIdentificationWasSentToServer()
{
Assert.AreEqual(5, _dataReceivedByServer.Count);
Assert.AreEqual(0xed, _dataReceivedByServer[0]);
Assert.AreEqual(0x95, _dataReceivedByServer[1]);
Assert.AreEqual(0x9c, _dataReceivedByServer[2]);
Assert.AreEqual(0x0d, _dataReceivedByServer[3]);
Assert.AreEqual(0x0a, _dataReceivedByServer[4]);
}
[TestMethod]
public void ConnectionIsClosedByServer()
{
Assert.IsTrue(_client.Connected);
Assert.IsFalse(_clientDisconnected);
var bytesReceived = _client.Receive(new byte[1]);
Assert.AreEqual(0, bytesReceived);
Assert.IsTrue(_client.Connected);
Assert.IsFalse(_clientDisconnected);
}
}
}
@@ -0,0 +1,132 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
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;
using System.Text;
namespace Renci.SshNet.Tests.Classes.Connection
{
[TestClass]
public class ProtocolVersionExchangeTest_ServerResponseContainsNullCharacter
{
private AsyncSocketListener _server;
private ProtocolVersionExchange _protocolVersionExchange;
private string _clientVersion;
private TimeSpan _timeout;
private IPEndPoint _serverEndPoint;
private List<byte> _dataReceivedByServer;
private byte[] _serverIdentification;
private bool _clientDisconnected;
private Socket _client;
private SshConnectionException _actualException;
[TestInitialize]
public void Setup()
{
Arrange();
Act();
}
[TestCleanup]
public void Cleanup()
{
if (_server != null)
{
_server.Dispose();
_server = null;
}
if (_client != null)
{
_client.Shutdown(SocketShutdown.Both);
_client.Close();
_client = null;
}
}
protected void Arrange()
{
_clientVersion = "SSH-2.0-Renci.SshNet.SshClient.0.0.1";
_timeout = TimeSpan.FromSeconds(5);
_serverEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
_dataReceivedByServer = new List<byte>();
_serverIdentification = Encoding.UTF8.GetBytes("\uD55C!\0\uD55CSSH -2.0-Renci.SshNet.SshClient.0.0.1");
_server = new AsyncSocketListener(_serverEndPoint);
_server.Start();
_server.Connected += socket => socket.Send(_serverIdentification);
_server.BytesReceived += (bytes, socket) =>
{
_dataReceivedByServer.AddRange(bytes);
};
_server.Disconnected += (socket) => _clientDisconnected = true;
_client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_client.Connect(_serverEndPoint);
_protocolVersionExchange = new ProtocolVersionExchange();
}
protected void Act()
{
try
{
_protocolVersionExchange.Start(_clientVersion, _client, _timeout);
Assert.Fail();
}
catch (SshConnectionException ex)
{
_actualException = ex;
}
}
[TestMethod]
public void StartShouldHaveThrownSshConnectionException()
{
var expectedMessage = string.Format("The server response contains a null character at position 0x00000005:{0}{0}" +
" 00000000 ED 95 9C 21 00 ...!.{0}{0}" +
"A server must not send a null character before the Protocol Version Exchange is complete.{0}{0}" +
"More information is available here:{0}" +
"https://tools.ietf.org/html/rfc4253#section-4.2",
Environment.NewLine);
Assert.IsNotNull(_actualException);
Assert.IsNull(_actualException.InnerException);
Assert.AreEqual(expectedMessage, _actualException.Message);
}
[TestMethod]
public void ClientIdentificationWasSentToServer()
{
var expected = Encoding.UTF8.GetBytes(_clientVersion);
Assert.AreEqual(expected.Length + 2, _dataReceivedByServer.Count);
Assert.IsTrue(expected.SequenceEqual(_dataReceivedByServer.Take(expected.Length)));
Assert.AreEqual(Session.CarriageReturn, _dataReceivedByServer[_dataReceivedByServer.Count - 2]);
Assert.AreEqual(Session.LineFeed, _dataReceivedByServer[_dataReceivedByServer.Count - 1]);
}
[TestMethod]
public void ClientRemainsConnected()
{
Assert.IsTrue(_client.Connected);
Assert.IsFalse(_clientDisconnected);
}
[TestMethod]
public void ClientHasNotReadPastNullCharacter()
{
var buffer = new byte[1];
var bytesReceived = _client.Receive(buffer);
Assert.AreEqual(1, bytesReceived);
Assert.AreEqual(0xed, buffer[0]);
}
}
}
@@ -0,0 +1,128 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
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;
using System.Text;
namespace Renci.SshNet.Tests.Classes.Connection
{
[TestClass]
public class ProtocolVersionExchangeTest_ServerResponseInvalid_SshIdentificationOnlyContainsProtocolVersion
{
private AsyncSocketListener _server;
private ProtocolVersionExchange _protocolVersionExchange;
private string _clientVersion;
private TimeSpan _timeout;
private IPEndPoint _serverEndPoint;
private List<byte> _dataReceivedByServer;
private byte[] _serverIdentification;
private bool _clientDisconnected;
private Socket _client;
private SshConnectionException _actualException;
[TestInitialize]
public void Setup()
{
Arrange();
Act();
}
[TestCleanup]
public void Cleanup()
{
if (_server != null)
{
_server.Dispose();
_server = null;
}
if (_client != null)
{
_client.Shutdown(SocketShutdown.Both);
_client.Close();
_client = null;
}
}
protected void Arrange()
{
_clientVersion = "SSH-2.0-Renci.SshNet.SshClient.0.0.1";
_timeout = TimeSpan.FromSeconds(5);
_serverEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
_dataReceivedByServer = new List<byte>();
_serverIdentification = Encoding.UTF8.GetBytes("SSH-2.0\r\n");
_server = new AsyncSocketListener(_serverEndPoint);
_server.Start();
_server.BytesReceived += (bytes, socket) =>
{
_dataReceivedByServer.AddRange(bytes);
socket.Send(_serverIdentification);
socket.Shutdown(SocketShutdown.Send);
};
_server.Disconnected += (socket) => _clientDisconnected = true;
_client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_client.Connect(_serverEndPoint);
_protocolVersionExchange = new ProtocolVersionExchange();
}
protected void Act()
{
try
{
_protocolVersionExchange.Start(_clientVersion, _client, _timeout);
Assert.Fail();
}
catch (SshConnectionException ex)
{
_actualException = ex;
}
}
[TestMethod]
public void StartShouldHaveThrownSshConnectionException()
{
var expectedMessage = string.Format("The server response does not contain an SSH identification string:{0}{0}" +
" 00000000 53 53 48 2D 32 2E 30 0D 0A SSH-2.0..{0}{0}" +
"More information on the Protocol Version Exchange is available here:{0}" +
"https://tools.ietf.org/html/rfc4253#section-4.2",
Environment.NewLine);
Assert.IsNotNull(_actualException);
Assert.IsNull(_actualException.InnerException);
Assert.AreEqual(expectedMessage, _actualException.Message);
}
[TestMethod]
public void ClientIdentificationWasSentToServer()
{
var expected = Encoding.UTF8.GetBytes(_clientVersion);
Assert.AreEqual(expected.Length + 2, _dataReceivedByServer.Count);
Assert.IsTrue(expected.SequenceEqual(_dataReceivedByServer.Take(expected.Length)));
Assert.AreEqual(Session.CarriageReturn, _dataReceivedByServer[_dataReceivedByServer.Count - 2]);
Assert.AreEqual(Session.LineFeed, _dataReceivedByServer[_dataReceivedByServer.Count - 1]);
}
[TestMethod]
public void ConnectionIsClosedByServer()
{
Assert.IsTrue(_client.Connected);
Assert.IsFalse(_clientDisconnected);
var bytesReceived = _client.Receive(new byte[1]);
Assert.AreEqual(0, bytesReceived);
Assert.IsTrue(_client.Connected);
Assert.IsFalse(_clientDisconnected);
}
}
}
@@ -0,0 +1,119 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
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;
using System.Text;
namespace Renci.SshNet.Tests.Classes.Connection
{
[TestClass]
public class ProtocolVersionExchangeTest_ServerResponseValid_Comments
{
private AsyncSocketListener _server;
private ProtocolVersionExchange _protocolVersionExchange;
private string _clientVersion;
private TimeSpan _timeout;
private IPEndPoint _serverEndPoint;
private List<byte> _dataReceivedByServer;
private byte[] _serverIdentification;
private bool _clientDisconnected;
private Socket _client;
private SshIdentification _actual;
[TestInitialize]
public void Setup()
{
Arrange();
Act();
}
[TestCleanup]
public void Cleanup()
{
if (_server != null)
{
_server.Dispose();
_server = null;
}
if (_client != null)
{
_client.Shutdown(SocketShutdown.Both);
_client.Close();
_client = null;
}
}
protected void Arrange()
{
_clientVersion = "SSH-2.0-Renci.SshNet.SshClient.0.0.1";
_timeout = TimeSpan.FromSeconds(5);
_serverEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
_dataReceivedByServer = new List<byte>();
_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.Send);
};
_server.Disconnected += (socket) => _clientDisconnected = true;
_client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_client.Connect(_serverEndPoint);
_protocolVersionExchange = new ProtocolVersionExchange();
}
protected void Act()
{
_actual = _protocolVersionExchange.Start(_clientVersion, _client, _timeout);
}
[TestMethod]
public void StartShouldReturnIdentificationOfServer()
{
Assert.IsNotNull(_actual);
Assert.AreEqual("ABC2.0", _actual.ProtocolVersion);
Assert.AreEqual("OurSSHAppliance-1.4.7", _actual.SoftwareVersion);
Assert.AreEqual("Use at own risk.\uD55C", _actual.Comments);
}
[TestMethod]
public void ClientIdentificationWasSentToServer()
{
var expected = Encoding.UTF8.GetBytes(_clientVersion);
Assert.AreEqual(expected.Length + 2, _dataReceivedByServer.Count);
Assert.IsTrue(expected.SequenceEqual(_dataReceivedByServer.Take(expected.Length)));
Assert.AreEqual(Session.CarriageReturn, _dataReceivedByServer[_dataReceivedByServer.Count - 2]);
Assert.AreEqual(Session.LineFeed, _dataReceivedByServer[_dataReceivedByServer.Count - 1]);
}
[TestMethod]
public void ClientRemainsConnected()
{
Assert.IsTrue(_client.Connected);
Assert.IsFalse(_clientDisconnected);
}
[TestMethod]
public void ClientDidNotReadPastIdentification()
{
var buffer = new byte[1];
var bytesReceived = _client.Receive(buffer);
Assert.AreEqual(1, bytesReceived);
Assert.AreEqual(0x21, buffer[0]);
}
}
}
@@ -0,0 +1,119 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
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;
using System.Text;
namespace Renci.SshNet.Tests.Classes.Connection
{
[TestClass]
public class ProtocolVersionExchangeTest_ServerResponseValid_NoComments
{
private AsyncSocketListener _server;
private ProtocolVersionExchange _protocolVersionExchange;
private string _clientVersion;
private TimeSpan _timeout;
private IPEndPoint _serverEndPoint;
private List<byte> _dataReceivedByServer;
private byte[] _serverIdentification;
private bool _clientDisconnected;
private Socket _client;
private SshIdentification _actual;
[TestInitialize]
public void Setup()
{
Arrange();
Act();
}
[TestCleanup]
public void Cleanup()
{
if (_server != null)
{
_server.Dispose();
_server = null;
}
if (_client != null)
{
_client.Shutdown(SocketShutdown.Both);
_client.Close();
_client = null;
}
}
protected void Arrange()
{
_clientVersion = "SSH-2.0-Renci.SshNet.SshClient.0.0.1";
_timeout = TimeSpan.FromSeconds(5);
_serverEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
_dataReceivedByServer = new List<byte>();
_serverIdentification = Encoding.UTF8.GetBytes("Welcome stranger!\r\n\r\nSSH-Zero-OurSSHAppliance\r\n!");
_server = new AsyncSocketListener(_serverEndPoint);
_server.Start();
_server.BytesReceived += (bytes, socket) =>
{
_dataReceivedByServer.AddRange(bytes);
socket.Send(_serverIdentification);
socket.Shutdown(SocketShutdown.Send);
};
_server.Disconnected += (socket) => _clientDisconnected = true;
_client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_client.Connect(_serverEndPoint);
_protocolVersionExchange = new ProtocolVersionExchange();
}
protected void Act()
{
_actual = _protocolVersionExchange.Start(_clientVersion, _client, _timeout);
}
[TestMethod]
public void StartShouldReturnIdentificationOfServer()
{
Assert.IsNotNull(_actual);
Assert.AreEqual("Zero", _actual.ProtocolVersion);
Assert.AreEqual("OurSSHAppliance", _actual.SoftwareVersion);
Assert.IsNull(_actual.Comments);
}
[TestMethod]
public void ClientIdentificationWasSentToServer()
{
var expected = Encoding.UTF8.GetBytes(_clientVersion);
Assert.AreEqual(expected.Length + 2, _dataReceivedByServer.Count);
Assert.IsTrue(expected.SequenceEqual(_dataReceivedByServer.Take(expected.Length)));
Assert.AreEqual(Session.CarriageReturn, _dataReceivedByServer[_dataReceivedByServer.Count - 2]);
Assert.AreEqual(Session.LineFeed, _dataReceivedByServer[_dataReceivedByServer.Count - 1]);
}
[TestMethod]
public void ClientRemainsConnected()
{
Assert.IsTrue(_client.Connected);
Assert.IsFalse(_clientDisconnected);
}
[TestMethod]
public void ClientDidNotReadPastIdentification()
{
var buffer = new byte[1];
var bytesReceived = _client.Receive(buffer);
Assert.AreEqual(1, bytesReceived);
Assert.AreEqual(0x21, buffer[0]);
}
}
}
@@ -0,0 +1,113 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
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;
using System.Text;
namespace Renci.SshNet.Tests.Classes.Connection
{
[TestClass]
public class ProtocolVersionExchangeTest_TimeoutReadingIdentificationString
{
private AsyncSocketListener _server;
private ProtocolVersionExchange _protocolVersionExchange;
private string _clientVersion;
private TimeSpan _timeout;
private IPEndPoint _serverEndPoint;
private List<byte> _dataReceivedByServer;
private bool _clientDisconnected;
private Socket _client;
private SshOperationTimeoutException _actualException;
[TestInitialize]
public void Setup()
{
Arrange();
Act();
}
[TestCleanup]
public void Cleanup()
{
if (_server != null)
{
_server.Dispose();
_server = null;
}
if (_client != null)
{
_client.Close();
_client = null;
}
}
protected void Arrange()
{
_clientVersion = "SSH-2.0-Renci.SshNet.SshClient.0.0.1";
_timeout = TimeSpan.FromMilliseconds(200);
_serverEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
_dataReceivedByServer = new List<byte>();
_clientDisconnected = false;
_server = new AsyncSocketListener(_serverEndPoint);
_server.Start();
_server.BytesReceived += (bytes, socket) =>
{
_dataReceivedByServer.AddRange(bytes);
socket.Send(Encoding.UTF8.GetBytes("Welcome!\r\n"));
};
_server.Disconnected += (socket) => _clientDisconnected = true;
_client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_client.Connect(_serverEndPoint);
_protocolVersionExchange = new ProtocolVersionExchange();
}
protected void Act()
{
try
{
_protocolVersionExchange.Start(_clientVersion, _client, _timeout);
Assert.Fail();
}
catch (SshOperationTimeoutException ex)
{
_actualException = ex;
}
}
[TestMethod]
public void StartShouldHaveThrownSshOperationTimeoutException()
{
Assert.IsNotNull(_actualException);
Assert.IsNull(_actualException.InnerException);
Assert.AreEqual(string.Format("Socket read operation has timed out after {0} milliseconds.", _timeout.TotalMilliseconds), _actualException.Message);
}
[TestMethod]
public void ClientIdentificationWasSentToServer()
{
var expected = Encoding.UTF8.GetBytes(_clientVersion);
Assert.AreEqual(expected.Length + 2, _dataReceivedByServer.Count);
Assert.IsTrue(expected.SequenceEqual(_dataReceivedByServer.Take(expected.Length)));
Assert.AreEqual(Session.CarriageReturn, _dataReceivedByServer[_dataReceivedByServer.Count - 2]);
Assert.AreEqual(Session.LineFeed, _dataReceivedByServer[_dataReceivedByServer.Count - 1]);
}
[TestMethod]
public void ClientSocketShouldBeConnected()
{
Assert.IsTrue(_client.Connected);
Assert.IsFalse(_clientDisconnected);
}
}
}
@@ -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"));
}
}
}
@@ -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;
}
}
}
}
}
@@ -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());
}
}
}
@@ -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());
}
}
}
@@ -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());
}
}
}
@@ -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());
}
}
}
@@ -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());
}
}
}
@@ -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();
}
}
}
@@ -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());
}
}
}
@@ -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());
}
}
}
@@ -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;
}
}
}
}
}
@@ -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());
}
}
}
@@ -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());
}
}
}
@@ -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());
}
}
}
@@ -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());
}
}
}
@@ -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,139 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Renci.SshNet.Connection;
using System;
namespace Renci.SshNet.Tests.Classes.Connection
{
[TestClass]
public class SshIdentificationTest
{
[TestMethod]
public void Ctor_ProtocolVersionAndSoftwareVersion()
{
const string protocolVersion = "1.5";
const string softwareVersion = "SSH.NET_2020.0.0";
var sshIdentification = new SshIdentification(protocolVersion, softwareVersion);
Assert.AreSame(protocolVersion, sshIdentification.ProtocolVersion);
Assert.AreSame(softwareVersion, sshIdentification.SoftwareVersion);
Assert.IsNull(sshIdentification.Comments);
}
[TestMethod]
public void Ctor_ProtocolVersionAndSoftwareVersion_ProtocolVersionIsNull()
{
const string protocolVersion = null;
const string softwareVersion = "SSH.NET_2020.0.0";
try
{
new SshIdentification(protocolVersion, softwareVersion);
Assert.Fail();
}
catch (ArgumentNullException ex)
{
Assert.IsNull(ex.InnerException);
Assert.AreEqual("protocolVersion", ex.ParamName);
}
}
[TestMethod]
public void Ctor_ProtocolVersionAndSoftwareVersion_SoftwareVersionIsNull()
{
const string protocolVersion = "2.0";
const string softwareVersion = null;
try
{
new SshIdentification(protocolVersion, softwareVersion);
Assert.Fail();
}
catch (ArgumentNullException ex)
{
Assert.IsNull(ex.InnerException);
Assert.AreEqual("softwareVersion", ex.ParamName);
}
}
[TestMethod]
public void Ctor_ProtocolVersionAndSoftwareVersionAndComments()
{
const string protocolVersion = "1.5";
const string softwareVersion = "SSH.NET_2020.0.0";
const string comments = "Beware, dangerous!";
var sshIdentification = new SshIdentification(protocolVersion, softwareVersion, comments);
Assert.AreSame(protocolVersion, sshIdentification.ProtocolVersion);
Assert.AreSame(softwareVersion, sshIdentification.SoftwareVersion);
Assert.AreSame(comments, sshIdentification.Comments);
}
[TestMethod]
public void Ctor_ProtocolVersionAndSoftwareVersionAndComments_CommentsIsNull()
{
const string protocolVersion = "1.5";
const string softwareVersion = "SSH.NET_2020.0.0";
const string comments = null;
var sshIdentification = new SshIdentification(protocolVersion, softwareVersion, comments);
Assert.AreSame(protocolVersion, sshIdentification.ProtocolVersion);
Assert.AreSame(softwareVersion, sshIdentification.SoftwareVersion);
Assert.IsNull(comments, sshIdentification.Comments);
}
[TestMethod]
public void Ctor_ProtocolVersionAndSoftwareVersionAndComments_ProtocolVersionIsNull()
{
const string protocolVersion = null;
const string softwareVersion = "SSH.NET_2020.0.0";
const string comments = "Beware!";
try
{
new SshIdentification(protocolVersion, softwareVersion, comments);
Assert.Fail();
}
catch (ArgumentNullException ex)
{
Assert.IsNull(ex.InnerException);
Assert.AreEqual("protocolVersion", ex.ParamName);
}
}
[TestMethod]
public void Ctor_ProtocolVersionAndSoftwareVersionAndComments_SoftwareVersionIsNull()
{
const string protocolVersion = "2.0";
const string softwareVersion = null;
const string comments = "Beware!";
try
{
new SshIdentification(protocolVersion, softwareVersion, comments);
Assert.Fail();
}
catch (ArgumentNullException ex)
{
Assert.IsNull(ex.InnerException);
Assert.AreEqual("softwareVersion", ex.ParamName);
}
}
[TestMethod]
public void ToString_Comments()
{
var sshIdentification = new SshIdentification("2.0", "SSH.NET", "Beware, dangerous");
Assert.AreEqual("SSH-2.0-SSH.NET Beware, dangerous", sshIdentification.ToString());
}
[TestMethod]
public void ToString_CommentsIsNull()
{
var sshIdentification = new SshIdentification("2.0", "SSH.NET_2020.0.0");
Assert.AreEqual("SSH-2.0-SSH.NET_2020.0.0", sshIdentification.ToString());
sshIdentification = new SshIdentification("2.0", "SSH.NET_2020.0.0", null);
Assert.AreEqual("SSH-2.0-SSH.NET_2020.0.0", sshIdentification.ToString());
}
}
}
@@ -30,7 +30,7 @@ namespace Renci.SshNet.Tests.Classes.Messages.Connection
[Ignore] // placeholder
public void ChannelExtendedDataMessageConstructorTest1()
{
uint localChannelNumber = 0; // TODO: Initialize to an appropriate value
//uint localChannelNumber = 0; // TODO: Initialize to an appropriate value
//ChannelExtendedDataMessage target = new ChannelExtendedDataMessage(localChannelNumber, null, null);
Assert.Inconclusive("TODO: Implement code to verify target");
}
@@ -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);
}
}
}
@@ -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();
}
}
@@ -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);
@@ -52,6 +55,10 @@ namespace Renci.SshNet.Tests.Classes
.Returns(false);
_channelSessionMock.InSequence(sequence).Setup(p => p.Dispose());
_pipeStreamMock.As<IDisposable>().InSequence(sequence).Setup(p => p.Dispose());
// On .NET Core, Dispose() in turn invokes Close() and since we're not mocking
// an interface, we need to expect this call as well
_pipeStreamMock.Setup(p => p.Close());
}
protected override void Arrange()
@@ -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);
@@ -51,6 +54,10 @@ namespace Renci.SshNet.Tests.Classes
.Setup(p => p.SendExecRequest(string.Format("scp -pf {0}", _transformedPath))).Returns(false);
_channelSessionMock.InSequence(sequence).Setup(p => p.Dispose());
_pipeStreamMock.As<IDisposable>().InSequence(sequence).Setup(p => p.Dispose());
// On .NET Core, Dispose() in turn invokes Close() and since we're not mocking
// an interface, we need to expect this call as well
_pipeStreamMock.Setup(p => p.Close());
}
protected override void Arrange()
@@ -19,15 +19,6 @@ namespace Renci.SshNet.Tests.Classes
private IList<ScpUploadEventArgs> _uploadingRegister;
private SshException _actualException;
[TestCleanup]
public void Cleanup()
{
if (_destination != null)
{
_destination.Dispose();
}
}
protected override void SetupData()
{
var random = new Random();
@@ -47,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);
@@ -61,6 +55,10 @@ namespace Renci.SshNet.Tests.Classes
.Returns(false);
_channelSessionMock.InSequence(sequence).Setup(p => p.Dispose());
_pipeStreamMock.As<IDisposable>().InSequence(sequence).Setup(p => p.Dispose());
// On .NET Core, Dispose() in turn invokes Close() and since we're not mocking
// an interface, we need to expect this call as well
_pipeStreamMock.Setup(p => p.Close());
}
protected override void Arrange()
@@ -72,6 +70,16 @@ namespace Renci.SshNet.Tests.Classes
_scpClient.Connect();
}
protected override void TearDown()
{
base.TearDown();
if (_destination != null)
{
_destination.Dispose();
}
}
protected override void Act()
{
try
@@ -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);
@@ -51,6 +54,10 @@ namespace Renci.SshNet.Tests.Classes
.Returns(false);
_channelSessionMock.InSequence(sequence).Setup(p => p.Dispose());
_pipeStreamMock.As<IDisposable>().InSequence(sequence).Setup(p => p.Dispose());
// On .NET Core, Dispose() in turn invokes Close() and since we're not mocking
// an interface, we need to expect this call as well
_pipeStreamMock.Setup(p => p.Close());
}
protected override void Arrange()
@@ -21,16 +21,6 @@ namespace Renci.SshNet.Tests.Classes
private IList<ScpUploadEventArgs> _uploadingRegister;
private SshException _actualException;
[TestCleanup]
public void Cleanup()
{
if (_fileName != null)
{
File.Delete(_fileName);
_fileName = null;
}
}
protected override void SetupData()
{
var random = new Random();
@@ -53,7 +43,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);
@@ -67,7 +60,11 @@ namespace Renci.SshNet.Tests.Classes
.Returns(false);
_channelSessionMock.InSequence(sequence).Setup(p => p.Dispose());
_pipeStreamMock.As<IDisposable>().InSequence(sequence).Setup(p => p.Dispose());
}
// On .NET Core, Dispose() in turn invokes Close() and since we're not mocking
// an interface, we need to expect this call as well
_pipeStreamMock.Setup(p => p.Close());
}
protected override void Arrange()
{
@@ -78,6 +75,17 @@ namespace Renci.SshNet.Tests.Classes
_scpClient.Connect();
}
protected override void TearDown()
{
base.TearDown();
if (_fileName != null)
{
File.Delete(_fileName);
_fileName = null;
}
}
protected override void Act()
{
try
@@ -25,16 +25,6 @@ namespace Renci.SshNet.Tests.Classes
private int _fileSize;
private IList<ScpUploadEventArgs> _uploadingRegister;
[TestCleanup]
public void Cleanup()
{
if (_fileName != null)
{
File.Delete(_fileName);
_fileName = null;
}
}
protected override void SetupData()
{
var random = new Random();
@@ -60,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);
@@ -92,6 +85,10 @@ namespace Renci.SshNet.Tests.Classes
_pipeStreamMock.InSequence(sequence).Setup(p => p.ReadByte()).Returns(0);
_channelSessionMock.InSequence(sequence).Setup(p => p.Dispose());
_pipeStreamMock.As<IDisposable>().InSequence(sequence).Setup(p => p.Dispose());
// On .NET Core, Dispose() in turn invokes Close() and since we're not mocking
// an interface, we need to expect this call as well
_pipeStreamMock.Setup(p => p.Close());
}
protected override void Arrange()
@@ -106,6 +103,17 @@ namespace Renci.SshNet.Tests.Classes
_scpClient.Connect();
}
protected override void TearDown()
{
base.TearDown();
if (_fileName != null)
{
File.Delete(_fileName);
_fileName = null;
}
}
protected override void Act()
{
_scpClient.Upload(_fileInfo, _remotePath);
@@ -20,15 +20,6 @@ namespace Renci.SshNet.Tests.Classes
private IList<ScpUploadEventArgs> _uploadingRegister;
private SshException _actualException;
[TestCleanup]
public void Cleanup()
{
if (_source != null)
{
_source.Dispose();
}
}
protected override void SetupData()
{
var random = new Random();
@@ -50,7 +41,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);
@@ -64,6 +58,10 @@ namespace Renci.SshNet.Tests.Classes
.Returns(false);
_channelSessionMock.InSequence(sequence).Setup(p => p.Dispose());
_pipeStreamMock.As<IDisposable>().InSequence(sequence).Setup(p => p.Dispose());
// On .NET Core, Dispose() in turn invokes Close() and since we're not mocking
// an interface, we need to expect this call as well
_pipeStreamMock.Setup(p => p.Close());
}
protected override void Arrange()
@@ -75,6 +73,16 @@ namespace Renci.SshNet.Tests.Classes
_scpClient.Connect();
}
protected override void TearDown()
{
base.TearDown();
if (_source != null)
{
_source.Dispose();
}
}
protected override void Act()
{
try
@@ -0,0 +1,140 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Renci.SshNet.Connection;
using System;
namespace Renci.SshNet.Tests.Classes
{
[TestClass]
public class ServiceFactoryTest_CreateConnector
{
private ServiceFactory _serviceFactory;
private Mock<IConnectionInfo> _connectionInfoMock;
private Mock<ISocketFactory> _socketFactoryMock;
[TestInitialize]
public void Setup()
{
_serviceFactory = new ServiceFactory();
_connectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
_socketFactoryMock = new Mock<ISocketFactory>(MockBehavior.Strict);
}
[TestMethod]
public void ConnectionInfoIsNull()
{
const IConnectionInfo connectionInfo = null;
try
{
_serviceFactory.CreateConnector(connectionInfo, _socketFactoryMock.Object);
Assert.Fail();
}
catch (ArgumentNullException ex)
{
Assert.IsNull(ex.InnerException);
Assert.AreEqual("connectionInfo", ex.ParamName);
}
}
[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, _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);
}
[TestMethod]
public void ProxyType_None()
{
_connectionInfoMock.Setup(p => p.ProxyType).Returns(ProxyTypes.None);
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);
}
[TestMethod]
public void ProxyType_Socks4()
{
_connectionInfoMock.Setup(p => p.ProxyType).Returns(ProxyTypes.Socks4);
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);
}
[TestMethod]
public void ProxyType_Socks5()
{
_connectionInfoMock.Setup(p => p.ProxyType).Returns(ProxyTypes.Socks5);
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.Exactly(2));
}
}
}
@@ -5,240 +5,13 @@ using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Renci.SshNet.Common;
using Renci.SshNet.Tests.Common;
using Renci.SshNet.Connection;
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();
using (var session = new Session(CreateConnectionInfoWithProxy(proxyEndPoint, serverEndPoint, "anon"), _serviceFactoryMock.Object))
{
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();
using (var session = new Session(CreateConnectionInfoWithProxy(proxyEndPoint, serverEndPoint, "anon"), _serviceFactoryMock.Object))
{
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();
using (var session = new Session(CreateConnectionInfoWithProxy(proxyEndPoint, serverEndPoint, "anon"), _serviceFactoryMock.Object))
{
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();
using (var session = new Session(CreateConnectionInfoWithProxy(proxyEndPoint, serverEndPoint, "anon"), _serviceFactoryMock.Object))
{
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();
using (var session = new Session(CreateConnectionInfoWithProxy(proxyEndPoint, serverEndPoint, "anon"), _serviceFactoryMock.Object))
{
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 = CreateConnectionInfoWithProxy(proxyEndPoint, serverEndPoint, "anon");
using (var session = new Session(connectionInfo, _serviceFactoryMock.Object))
{
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 = CreateConnectionInfoWithProxy(proxyEndPoint, serverEndPoint, string.Empty);
using (var session = new Session(connectionInfo, _serviceFactoryMock.Object))
{
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 = CreateConnectionInfoWithProxy(proxyEndPoint, serverEndPoint, null);
using (var session = new Session(connectionInfo, _serviceFactoryMock.Object))
{
try
{
session.Connect();
Assert.Fail();
}
catch (ProxyException)
{
}
}
Assert.IsFalse(proxyStub.HttpRequest.Headers.Any(p => p.StartsWith("Proxy-Authorization:")));
}
}
private static ConnectionInfo CreateConnectionInfoWithProxy(IPEndPoint proxyEndPoint, IPEndPoint serverEndPoint, string proxyUserName)
private static ConnectionInfo CreateConnectionInfoWithHttpProxy(IPEndPoint proxyEndPoint, IPEndPoint serverEndPoint, string proxyUserName)
{
return new ConnectionInfo(
serverEndPoint.Address.ToString(),
+16 -331
View File
@@ -1,15 +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.Messages.Transport;
using Renci.SshNet.Connection;
using Renci.SshNet.Tests.Common;
using Renci.SshNet.Tests.Properties;
namespace Renci.SshNet.Tests.Classes
{
@@ -20,23 +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)
@@ -55,7 +54,7 @@ namespace Renci.SshNet.Tests.Classes
try
{
new Session(connectionInfo, serviceFactory);
new Session(connectionInfo, serviceFactory, _socketFactoryMock.Object);
Assert.Fail();
}
catch (ArgumentNullException ex)
@@ -66,338 +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))
{
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))
{
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))
{
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();
using (var session = new Session(CreateConnectionInfo(serverEndPoint, TimeSpan.FromMilliseconds(500)), _serviceFactoryMock.Object))
{
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();
using (var session = new Session(CreateConnectionInfo(serverEndPoint, TimeSpan.FromSeconds(5)), _serviceFactoryMock.Object))
{
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();
using (var session = new Session(CreateConnectionInfo(serverEndPoint, TimeSpan.FromSeconds(5)), _serviceFactoryMock.Object))
{
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();
using (var session = new Session(CreateConnectionInfo(serverEndPoint, TimeSpan.FromSeconds(5)), _serviceFactoryMock.Object))
{
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);
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);
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);
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);
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;
}
}
}
@@ -1,6 +1,7 @@
using System;
using System.Threading;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Renci.SshNet.Messages.Transport;
namespace Renci.SshNet.Tests.Classes
@@ -65,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]
@@ -251,5 +252,24 @@ namespace Renci.SshNet.Tests.Classes
Assert.IsNull(exception);
}
}
[TestMethod]
public void ClientSocketShouldBeConnected()
{
Assert.IsNotNull(ClientSocket);
Assert.IsTrue(ClientSocket.Connected);
}
[TestMethod]
public void CreateConnectorOnServiceFactoryShouldHaveBeenInvokedOnce()
{
ServiceFactoryMock.Verify(p => p.CreateConnector(ConnectionInfo, SocketFactoryMock.Object), Times.Once());
}
[TestMethod]
public void ConnectorOnConnectorShouldHaveBeenInvokedOnce()
{
ConnectorMock.Verify(p => p.Connect(ConnectionInfo), Times.Once());
}
}
}
@@ -9,6 +9,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Renci.SshNet.Common;
using Renci.SshNet.Compression;
using Renci.SshNet.Connection;
using Renci.SshNet.Messages;
using Renci.SshNet.Messages.Transport;
using Renci.SshNet.Security;
@@ -20,11 +21,17 @@ namespace Renci.SshNet.Tests.Classes
[TestClass]
public abstract class SessionTest_ConnectedBase
{
private Mock<IServiceFactory> _serviceFactoryMock;
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; }
@@ -35,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; }
[TestInitialize]
public void Setup()
@@ -64,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()
@@ -84,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);
@@ -102,56 +120,65 @@ 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);
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(
ServiceFactoryMock.Setup(p => p.CreateConnector(ConnectionInfo, SocketFactoryMock.Object))
.Returns(ConnectorMock.Object);
ConnectorMock.Setup(p => p.Connect(ConnectionInfo))
.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);
_keyExchangeMock.Setup(p => p.Name).Returns(_keyExchangeAlgorithm);
@@ -164,19 +191,18 @@ namespace Renci.SshNet.Tests.Classes
_keyExchangeMock.Setup(p => p.CreateCompressor()).Returns((Compressor) null);
_keyExchangeMock.Setup(p => p.CreateDecompressor()).Returns((Compressor) null);
_keyExchangeMock.Setup(p => p.Dispose());
_serviceFactoryMock.Setup(p => p.CreateClientAuthentication())
ServiceFactoryMock.Setup(p => p.CreateClientAuthentication())
.Callback(ClientAuthentication_Callback)
.Returns(_clientAuthenticationMock.Object);
_clientAuthenticationMock.Setup(p => p.Authenticate(ConnectionInfo, Session));
}
protected virtual void Arrange()
protected void Arrange()
{
CreateMocks();
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,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());
}
}
}
@@ -4,11 +4,11 @@ using System.Globalization;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Renci.SshNet.Common;
using Renci.SshNet.Compression;
using Renci.SshNet.Connection;
using Renci.SshNet.Messages;
using Renci.SshNet.Messages.Transport;
using Renci.SshNet.Security;
@@ -21,11 +21,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; }
@@ -36,7 +41,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()
{
@@ -49,6 +56,12 @@ namespace Renci.SshNet.Tests.Classes
{
Session.Dispose();
}
if (ClientSocket != null && ClientSocket.Connected)
{
ClientSocket.Shutdown(SocketShutdown.Both);
ClientSocket.Dispose();
}
}
protected virtual void SetupData()
@@ -69,39 +82,31 @@ 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
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],
@@ -114,26 +119,46 @@ namespace Renci.SshNet.Tests.Classes
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 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, _socketFactoryMock.Object))
.Returns(_connectorMock.Object);
_connectorMock.Setup(p => p.Connect(ConnectionInfo))
.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);
@@ -157,7 +182,6 @@ namespace Renci.SshNet.Tests.Classes
SetupData();
SetupMocks();
ServerListener.Start();
Session.Connect();
}
@@ -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]
@@ -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]
@@ -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,10 +1,10 @@
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
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;
@@ -14,12 +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()
@@ -37,7 +42,15 @@ namespace Renci.SshNet.Tests.Classes
}
}
protected void Arrange()
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()
{
_serverEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
_connectionInfo = new ConnectionInfo(
@@ -47,32 +60,51 @@ namespace Renci.SshNet.Tests.Classes
new PasswordAuthenticationMethod("user", "password"));
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(200);
_actualException = null;
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
_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) =>
{
var badPacket = new byte[] {0x0a, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05};
// 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, _socketFactoryMock.Object))
.Returns(_connectorMock.Object);
_connectorMock.Setup(p => p.Connect(_connectionInfo))
.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()
{
CreateMocks();
SetupData();
SetupMocks();
}
protected virtual void Act()
{
try
{
using (_session = new Session(_connectionInfo, _serviceFactoryMock.Object))
{
_session.Connect();
}
@@ -38,7 +38,8 @@ namespace Renci.SshNet.Tests.Classes.Sftp
protected static SftpFileAttributes CreateSftpFileAttributes(long size)
{
return new SftpFileAttributes(default(DateTime), default(DateTime), size, default(int), default(int), default(uint), null);
var utcDefault = DateTime.SpecifyKind(default(DateTime), DateTimeKind.Utc);
return new SftpFileAttributes(utcDefault, utcDefault, size, default(int), default(int), default(uint), null);
}
protected static byte[] CreateByteArray(Random random, int length)
@@ -24,7 +24,7 @@ namespace Renci.SshNet.Tests.Classes.Sftp
var random = new Random();
_path = random.Next().ToString();
_handle = GenerateRandom(3, random);
_bufferSize = (uint) random.Next(0, 1000);
_bufferSize = (uint) random.Next(1, 1000);
_readBufferSize = (uint) random.Next(0, 1000);
_writeBufferSize = (uint) random.Next(0, 1000);
}
@@ -34,8 +34,8 @@ namespace Renci.SshNet.Tests.Classes.Sftp
_readBufferSize = (uint) _random.Next(5, 1000);
_writeBufferSize = (uint) _random.Next(5, 1000);
_handle = GenerateRandom(_random.Next(1, 10), _random);
_fileAttributes = new SftpFileAttributesBuilder().WithLastAccessTime(DateTime.Now.AddSeconds(_random.Next()))
.WithLastWriteTime(DateTime.Now.AddSeconds(_random.Next()))
_fileAttributes = new SftpFileAttributesBuilder().WithLastAccessTime(DateTime.UtcNow.AddSeconds(_random.Next()))
.WithLastWriteTime(DateTime.UtcNow.AddSeconds(_random.Next()))
.WithSize(_random.Next())
.WithUserId(_random.Next())
.WithGroupId(_random.Next())
@@ -53,8 +53,8 @@ namespace Renci.SshNet.Tests.Classes.Sftp
_fileAttributes = new SftpFileAttributesBuilder().WithExtension("X", "ABC")
.WithExtension("V", "VValue")
.WithGroupId(random.Next())
.WithLastAccessTime(DateTime.Now.AddSeconds(random.Next()))
.WithLastWriteTime(DateTime.Now.AddSeconds(random.Next()))
.WithLastAccessTime(DateTime.UtcNow.AddSeconds(random.Next()))
.WithLastWriteTime(DateTime.UtcNow.AddSeconds(random.Next()))
.WithPermissions((uint) random.Next())
.WithSize(_length + 100)
.WithUserId(random.Next())
@@ -201,4 +201,4 @@ namespace Renci.SshNet.Tests.Classes.Sftp
SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(4));
}
}
}
}
@@ -50,8 +50,8 @@ namespace Renci.SshNet.Tests.Classes.Sftp
_fileAttributes = new SftpFileAttributesBuilder().WithExtension("X", "ABC")
.WithExtension("V", "VValue")
.WithGroupId(random.Next())
.WithLastAccessTime(DateTime.Now.AddSeconds(random.Next()))
.WithLastWriteTime(DateTime.Now.AddSeconds(random.Next()))
.WithLastAccessTime(DateTime.UtcNow.AddSeconds(random.Next()))
.WithLastWriteTime(DateTime.UtcNow.AddSeconds(random.Next()))
.WithPermissions((uint)random.Next())
.WithSize(_length + 100)
.WithUserId(random.Next())
@@ -54,8 +54,8 @@ namespace Renci.SshNet.Tests.Classes.Sftp
_fileAttributes = new SftpFileAttributesBuilder().WithExtension("X", "ABC")
.WithExtension("V", "VValue")
.WithGroupId(random.Next())
.WithLastAccessTime(DateTime.Now.AddSeconds(random.Next()))
.WithLastWriteTime(DateTime.Now.AddSeconds(random.Next()))
.WithLastAccessTime(DateTime.UtcNow.AddSeconds(random.Next()))
.WithLastWriteTime(DateTime.UtcNow.AddSeconds(random.Next()))
.WithPermissions((uint)random.Next())
.WithSize(_length + 100)
.WithUserId(random.Next())
@@ -54,8 +54,8 @@ namespace Renci.SshNet.Tests.Classes.Sftp
_fileAttributes = new SftpFileAttributesBuilder().WithExtension("X", "ABC")
.WithExtension("V", "VValue")
.WithGroupId(random.Next())
.WithLastAccessTime(DateTime.Now.AddSeconds(random.Next()))
.WithLastWriteTime(DateTime.Now.AddSeconds(random.Next()))
.WithLastAccessTime(DateTime.UtcNow.AddSeconds(random.Next()))
.WithLastWriteTime(DateTime.UtcNow.AddSeconds(random.Next()))
.WithPermissions((uint) random.Next())
.WithSize(_length + 100)
.WithUserId(random.Next())

Some files were not shown because too many files have changed in this diff Show More