|
|
@@ -0,0 +1,116 @@
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Diagnostics;
|
|
|
+using System.Net;
|
|
|
+using System.Net.Sockets;
|
|
|
+
|
|
|
+using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
|
+
|
|
|
+using Moq;
|
|
|
+
|
|
|
+using Renci.SshNet.Common;
|
|
|
+using Renci.SshNet.Tests.Common;
|
|
|
+
|
|
|
+namespace Renci.SshNet.Tests.Classes.Connection
|
|
|
+{
|
|
|
+ [TestClass]
|
|
|
+ public class Socks5ConnectorTest_Connect_TimeoutConnectionReply : Socks5ConnectorTestBase
|
|
|
+ {
|
|
|
+ private ConnectionInfo _connectionInfo;
|
|
|
+ private Exception _actualException;
|
|
|
+ private AsyncSocketListener _proxyServer;
|
|
|
+ private Socket _clientSocket;
|
|
|
+ private List<byte> _bytesReceivedByProxy;
|
|
|
+ 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();
|
|
|
+ _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) {
|
|
|
+ _ = socket.Send(new byte[]
|
|
|
+ {
|
|
|
+ // SOCKS version
|
|
|
+ 0x05,
|
|
|
+ // Require no authentication
|
|
|
+ 0x00
|
|
|
+ });
|
|
|
+ }
|
|
|
+ };
|
|
|
+ _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();
|
|
|
+
|
|
|
+ _proxyServer?.Dispose();
|
|
|
+ _clientSocket?.Dispose();
|
|
|
+ }
|
|
|
+
|
|
|
+ protected override void Act()
|
|
|
+ {
|
|
|
+ _stopWatch.Start();
|
|
|
+
|
|
|
+ try
|
|
|
+ {
|
|
|
+ _ = Connector.Connect(_connectionInfo);
|
|
|
+ Assert.Fail();
|
|
|
+ }
|
|
|
+ catch (SocketException ex) {
|
|
|
+ _actualException = ex;
|
|
|
+ }
|
|
|
+ catch (SshOperationTimeoutException ex) {
|
|
|
+ _actualException = ex;
|
|
|
+ }
|
|
|
+ finally
|
|
|
+ {
|
|
|
+ _stopWatch.Stop();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ [TestMethod]
|
|
|
+ public void ConnectShouldHaveThrownSshOperationTimeoutException() {
|
|
|
+ Assert.IsNull(_actualException.InnerException);
|
|
|
+ Assert.IsInstanceOfType<SshOperationTimeoutException>(_actualException);
|
|
|
+ }
|
|
|
+
|
|
|
+ [TestMethod]
|
|
|
+ public void ConnectShouldHaveRespectedTimeout()
|
|
|
+ {
|
|
|
+ var errorText = string.Format("Elapsed: {0}, Timeout: {1}",
|
|
|
+ _stopWatch.ElapsedMilliseconds,
|
|
|
+ _connectionInfo.Timeout.TotalMilliseconds);
|
|
|
+
|
|
|
+ // Compare elapsed time with configured timeout, allowing for a margin of error
|
|
|
+ Assert.IsTrue(_stopWatch.ElapsedMilliseconds >= _connectionInfo.Timeout.TotalMilliseconds - 10, errorText);
|
|
|
+ Assert.IsTrue(_stopWatch.ElapsedMilliseconds < _connectionInfo.Timeout.TotalMilliseconds + 100, errorText);
|
|
|
+ }
|
|
|
+
|
|
|
+ [TestMethod]
|
|
|
+ public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce()
|
|
|
+ {
|
|
|
+ SocketFactoryMock.Verify(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp),
|
|
|
+ Times.Once());
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|