mirror of
https://github.com/sshnet/SSH.NET.git
synced 2026-09-10 09:15:47 +00:00
Port shared tests folder (#1467)
These tests were presumably once shared with the old integration tests repo but have since been sat doing nothing. This brings them into the unit tests project. Co-authored-by: Wojciech Nagórski <wojtpl2@gmail.com>
This commit is contained in:
@@ -292,7 +292,7 @@ namespace Renci.SshNet.Abstractions
|
||||
{
|
||||
if (IsErrorResumable(ex.SocketErrorCode))
|
||||
{
|
||||
ThreadAbstraction.Sleep(30);
|
||||
Thread.Sleep(30);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -346,7 +346,7 @@ namespace Renci.SshNet.Abstractions
|
||||
if (IsErrorResumable(ex.SocketErrorCode))
|
||||
{
|
||||
// socket buffer is probably full, wait and try again
|
||||
ThreadAbstraction.Sleep(30);
|
||||
Thread.Sleep(30);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -6,15 +6,6 @@ namespace Renci.SshNet.Abstractions
|
||||
{
|
||||
internal static class ThreadAbstraction
|
||||
{
|
||||
/// <summary>
|
||||
/// Suspends the current thread for the specified number of milliseconds.
|
||||
/// </summary>
|
||||
/// <param name="millisecondsTimeout">The number of milliseconds for which the thread is suspended.</param>
|
||||
public static void Sleep(int millisecondsTimeout)
|
||||
{
|
||||
Thread.Sleep(millisecondsTimeout);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and starts a long-running <see cref="Task"/> for the specified <see cref="Action"/>.
|
||||
/// </summary>
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Renci.SshNet
|
||||
private readonly bool[] _activatedMessagesById;
|
||||
private readonly object _lock = new object();
|
||||
|
||||
private static readonly MessageMetadata[] AllMessages = new MessageMetadata[]
|
||||
internal static readonly MessageMetadata[] AllMessages = new MessageMetadata[]
|
||||
{
|
||||
new MessageMetadata<KeyExchangeInitMessage>(0, "SSH_MSG_KEXINIT", 20),
|
||||
new MessageMetadata<NewKeysMessage>(1, "SSH_MSG_NEWKEYS", 21),
|
||||
@@ -263,7 +263,7 @@ namespace Renci.SshNet
|
||||
currentEnabledForMessageName));
|
||||
}
|
||||
|
||||
private abstract class MessageMetadata
|
||||
internal abstract class MessageMetadata
|
||||
{
|
||||
protected MessageMetadata(byte id, string name, byte number)
|
||||
{
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Renci.SshNet.Abstractions;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Renci.SshNet.Tests.Abstractions
|
||||
{
|
||||
[TestClass]
|
||||
public class CryptoAbstraction_GenerateRandom
|
||||
{
|
||||
[TestMethod]
|
||||
public void ShouldThrowArgumentNullExceptionWhenDataIsNull()
|
||||
{
|
||||
const byte[] data = null;
|
||||
|
||||
try
|
||||
{
|
||||
CryptoAbstraction.GenerateRandom(data);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ArgumentNullException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("data", ex.ParamName);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldPerformNoOpWhenDataIsZeroLength()
|
||||
{
|
||||
var data = new byte[0];
|
||||
|
||||
CryptoAbstraction.GenerateRandom(data);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldGenerateRandomSequenceOfValues()
|
||||
{
|
||||
var dataLength = new Random().Next(1, 100);
|
||||
var dataA = new byte[dataLength];
|
||||
var dataB = new byte[dataLength];
|
||||
|
||||
CryptoAbstraction.GenerateRandom(dataA);
|
||||
CryptoAbstraction.GenerateRandom(dataB);
|
||||
|
||||
Assert.IsFalse(dataA.SequenceEqual(dataB));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Renci.SshNet.Abstractions;
|
||||
|
||||
namespace Renci.SshNet.Tests.Abstractions
|
||||
{
|
||||
[TestClass]
|
||||
public class DnsAbstraction_GetHostAddresses
|
||||
{
|
||||
[TestMethod]
|
||||
public void ShouldThrowArgumentNullExceptionWhenHostNameOrAddressIsNull()
|
||||
{
|
||||
const string hostNameOrAddress = null;
|
||||
|
||||
try
|
||||
{
|
||||
DnsAbstraction.GetHostAddresses(hostNameOrAddress);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ArgumentNullException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldThrowSocketExceptionWhenHostIsNotFound()
|
||||
{
|
||||
const string hostNameOrAddress = "surelydoesnotexist.OrAmIWrong";
|
||||
|
||||
try
|
||||
{
|
||||
var addresses = DnsAbstraction.GetHostAddresses(hostNameOrAddress);
|
||||
Assert.Fail(addresses.ToString());
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual(SocketError.HostNotFound, ex.SocketErrorCode);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnHostAddressesOfLocalHostWhenHostNameOrAddressIsEmpty()
|
||||
{
|
||||
const string hostNameOrAddress = "";
|
||||
|
||||
var addresses = DnsAbstraction.GetHostAddresses(hostNameOrAddress);
|
||||
Assert.IsNotNull(addresses);
|
||||
|
||||
var hostEntry = Dns.GetHostEntry(Dns.GetHostName());
|
||||
Assert.IsNotNull(hostEntry);
|
||||
|
||||
Assert.AreEqual(hostEntry.AddressList.Length, addresses.Length);
|
||||
for (var i = 0; i < hostEntry.AddressList.Length; i++)
|
||||
Assert.AreEqual(hostEntry.AddressList[i], addresses[i]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnSingleIpv4AddressWhenHostNameOrAddressIsValidIpv4Address()
|
||||
{
|
||||
const string hostNameOrAddress = "1.2.3.4";
|
||||
|
||||
var addresses = DnsAbstraction.GetHostAddresses(hostNameOrAddress);
|
||||
Assert.IsNotNull(addresses);
|
||||
Assert.AreEqual(1, addresses.Length);
|
||||
Assert.AreEqual(AddressFamily.InterNetwork, addresses[0].AddressFamily);
|
||||
Assert.AreEqual(IPAddress.Parse(hostNameOrAddress), addresses[0]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnSingleIpv6AddressWhenHostNameOrAddressIsValidIpv6Address()
|
||||
{
|
||||
const string hostNameOrAddress = "2001:0:9d38:90d7:384f:2133:ab3d:d152";
|
||||
|
||||
var addresses = DnsAbstraction.GetHostAddresses(hostNameOrAddress);
|
||||
Assert.IsNotNull(addresses);
|
||||
Assert.AreEqual(1, addresses.Length);
|
||||
Assert.AreEqual(AddressFamily.InterNetworkV6, addresses[0].AddressFamily);
|
||||
Assert.AreEqual(IPAddress.Parse(hostNameOrAddress), addresses[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Renci.SshNet.Abstractions;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Renci.SshNet.Tests.Abstractions
|
||||
{
|
||||
[TestClass]
|
||||
public class FileSystemAbstraction_EnumerateFiles
|
||||
{
|
||||
private string _temporaryDirectory;
|
||||
|
||||
[TestInitialize]
|
||||
public void SetUp()
|
||||
{
|
||||
_temporaryDirectory = Path.GetTempFileName();
|
||||
File.Delete(_temporaryDirectory);
|
||||
Directory.CreateDirectory(_temporaryDirectory);
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void TearDown()
|
||||
{
|
||||
if (_temporaryDirectory != null && Directory.Exists(_temporaryDirectory))
|
||||
{
|
||||
Directory.Delete(_temporaryDirectory, true);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldThrowArgumentNullExceptionWhenDirectoryInfoIsNull()
|
||||
{
|
||||
const DirectoryInfo directoryInfo = null;
|
||||
const string searchPattern = "*.xml";
|
||||
|
||||
try
|
||||
{
|
||||
FileSystemAbstraction.EnumerateFiles(directoryInfo, searchPattern);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ArgumentNullException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("directoryInfo", ex.ParamName);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldThrowArgumentNullExceptionWhenSearchPatternIsNull()
|
||||
{
|
||||
var directoryInfo = new DirectoryInfo(_temporaryDirectory);
|
||||
const string searchPattern = null;
|
||||
|
||||
try
|
||||
{
|
||||
FileSystemAbstraction.EnumerateFiles(directoryInfo, searchPattern);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ArgumentNullException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("searchPattern", ex.ParamName);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldThrowDirectoryNotFoundExceptionWhenDirectoryDoesNotExist()
|
||||
{
|
||||
var directoryInfo = new DirectoryInfo(_temporaryDirectory);
|
||||
const string searchPattern = "*.xml";
|
||||
|
||||
Directory.Delete(_temporaryDirectory, true);
|
||||
|
||||
try
|
||||
{
|
||||
FileSystemAbstraction.EnumerateFiles(directoryInfo, searchPattern);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnEmptyEnumerableWhenNoFilesExistInDirectory()
|
||||
{
|
||||
var directoryInfo = new DirectoryInfo(_temporaryDirectory);
|
||||
const string searchPattern = "*.xml";
|
||||
|
||||
var actual = FileSystemAbstraction.EnumerateFiles(directoryInfo, searchPattern);
|
||||
|
||||
Assert.IsFalse(actual.GetEnumerator().MoveNext());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnEmptyEnumerableWhenNoFilesMatchSearchPatternExistInDirectory()
|
||||
{
|
||||
CreateFile(Path.Combine(_temporaryDirectory, "test.txt"));
|
||||
|
||||
var directoryInfo = new DirectoryInfo(_temporaryDirectory);
|
||||
const string searchPattern = "*.xml";
|
||||
|
||||
var actual = FileSystemAbstraction.EnumerateFiles(directoryInfo, searchPattern);
|
||||
|
||||
Assert.IsFalse(actual.GetEnumerator().MoveNext());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnEmptyEnumerableWhenSearchPatternIsEmpty()
|
||||
{
|
||||
CreateFile(Path.Combine(_temporaryDirectory, "test.txt"));
|
||||
|
||||
var directoryInfo = new DirectoryInfo(_temporaryDirectory);
|
||||
const string searchPattern = "";
|
||||
|
||||
var actual = FileSystemAbstraction.EnumerateFiles(directoryInfo, searchPattern);
|
||||
|
||||
Assert.IsFalse(actual.GetEnumerator().MoveNext());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnAllFilesInDirectoryWhenSearchPatternIsAsterisk()
|
||||
{
|
||||
CreateFile(Path.Combine(_temporaryDirectory, "test.txt"));
|
||||
CreateFile(Path.Combine(_temporaryDirectory, "test.xml"));
|
||||
|
||||
var directoryInfo = new DirectoryInfo(_temporaryDirectory);
|
||||
const string searchPattern = "*";
|
||||
|
||||
var actual = FileSystemAbstraction.EnumerateFiles(directoryInfo, searchPattern).ToList();
|
||||
|
||||
Assert.AreEqual(2, actual.Count);
|
||||
Assert.IsTrue(actual.Exists(p => p.Name == "test.txt"));
|
||||
Assert.IsTrue(actual.Exists(p => p.Name == "test.xml"));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldReturnOnlyReturnFilesFromTopLevelDirectory()
|
||||
{
|
||||
CreateFile(Path.Combine(_temporaryDirectory, "test.txt"));
|
||||
CreateFile(Path.Combine(_temporaryDirectory, "test.xml"));
|
||||
Directory.CreateDirectory(Path.Combine(_temporaryDirectory, "sub"));
|
||||
CreateFile(Path.Combine(_temporaryDirectory, "sub", "test.csv"));
|
||||
|
||||
var directoryInfo = new DirectoryInfo(_temporaryDirectory);
|
||||
const string searchPattern = "*";
|
||||
|
||||
var actual = FileSystemAbstraction.EnumerateFiles(directoryInfo, searchPattern).ToList();
|
||||
|
||||
Assert.AreEqual(2, actual.Count);
|
||||
Assert.IsTrue(actual.Exists(p => p.Name == "test.txt"));
|
||||
Assert.IsTrue(actual.Exists(p => p.Name == "test.xml"));
|
||||
}
|
||||
|
||||
private static void CreateFile(string fileName)
|
||||
{
|
||||
var fs = File.Create(fileName);
|
||||
fs.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
using System.Net.Sockets;
|
||||
using Renci.SshNet.Abstractions;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Renci.SshNet.Tests.Abstractions
|
||||
{
|
||||
[TestClass]
|
||||
public class SocketAbstraction_CanWrite
|
||||
{
|
||||
[TestMethod]
|
||||
public void ShouldReturnFalseWhenSocketIsNull()
|
||||
{
|
||||
const Socket socket = null;
|
||||
|
||||
var actual = SocketAbstraction.CanWrite(socket);
|
||||
|
||||
Assert.IsFalse(actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Renci.SshNet.Abstractions;
|
||||
|
||||
namespace Renci.SshNet.Tests.Abstractions
|
||||
{
|
||||
[TestClass]
|
||||
public class ThreadAbstraction_ExecuteThread
|
||||
{
|
||||
[TestMethod]
|
||||
public void ShouldThrowArgumentNullExceptionWhenActionIsNull()
|
||||
{
|
||||
const Action action = null;
|
||||
|
||||
try
|
||||
{
|
||||
ThreadAbstraction.ExecuteThread(action);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ArgumentNullException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("action", ex.ParamName);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ShouldExecuteActionOnSeparateThread()
|
||||
{
|
||||
DateTime? executionTime = null;
|
||||
int executionCount = 0;
|
||||
EventWaitHandle waitHandle = new ManualResetEvent(false);
|
||||
|
||||
Action action = () =>
|
||||
{
|
||||
ThreadAbstraction.Sleep(500);
|
||||
executionCount++;
|
||||
executionTime = DateTime.Now;
|
||||
waitHandle.Set();
|
||||
};
|
||||
|
||||
DateTime start = DateTime.Now;
|
||||
|
||||
ThreadAbstraction.ExecuteThread(action);
|
||||
|
||||
Assert.AreEqual(0, executionCount);
|
||||
Assert.IsNull(executionTime);
|
||||
|
||||
Assert.IsTrue(waitHandle.WaitOne(2000));
|
||||
|
||||
Assert.AreEqual(1, executionCount);
|
||||
Assert.IsNotNull(executionTime);
|
||||
|
||||
var elapsedTime = executionTime.Value - start;
|
||||
Assert.IsTrue(elapsedTime > TimeSpan.Zero);
|
||||
Assert.IsTrue(elapsedTime > TimeSpan.FromMilliseconds(500));
|
||||
Assert.IsTrue(elapsedTime < TimeSpan.FromMilliseconds(1000));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
||||
<HasSharedItems>true</HasSharedItems>
|
||||
<SharedGUID>fae3948f-a438-458e-8e0e-7f6e39a5dd8a</SharedGUID>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration">
|
||||
<Import_RootNamespace>Renci.SshNet.Tests</Import_RootNamespace>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Abstractions\CryptoAbstraction_GenerateRandom.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Abstractions\DnsAbstraction_GetHostAddresses.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Abstractions\FileSystemAbstraction_EnumerateFiles.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Abstractions\SocketAbstraction_CanWrite.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Abstractions\ThreadAbstraction_ExecuteThread.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ForwardedPortStatusTest_Started.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ForwardedPortStatusTest_Starting.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ForwardedPortStatusTest_Stopped.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ForwardedPortStatusTest_Stopping.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)SshMessageFactoryTest.cs" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,13 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>fae3948f-a438-458e-8e0e-7f6e39a5dd8a</ProjectGuid>
|
||||
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
|
||||
<PropertyGroup />
|
||||
<Import Project="Renci.SshNet.Shared.Tests.projitems" Label="Shared" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
|
||||
</Project>
|
||||
@@ -1,982 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Messages;
|
||||
using Renci.SshNet.Messages.Authentication;
|
||||
using Renci.SshNet.Messages.Connection;
|
||||
using Renci.SshNet.Messages.Transport;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Renci.SshNet.Tests
|
||||
{
|
||||
[TestClass]
|
||||
public class SshMessageFactoryTest
|
||||
{
|
||||
private SshMessageFactory _sshMessageFactory;
|
||||
private SshMessageFactoryOriginal _sshMessageFactoryOriginal;
|
||||
|
||||
[TestInitialize]
|
||||
public void SetUp()
|
||||
{
|
||||
_sshMessageFactory = new SshMessageFactory();
|
||||
_sshMessageFactoryOriginal = new SshMessageFactoryOriginal();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateShouldThrowSshExceptionWhenMessageIsNotEnabled()
|
||||
{
|
||||
const byte messageNumber = 60;
|
||||
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.Create(messageNumber);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid in the current context.", messageNumber), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateShouldThrowSshExceptionWhenMessageDoesNotExist_OutsideOfMessageNumberRange()
|
||||
{
|
||||
const byte messageNumber = 255;
|
||||
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.Create(messageNumber);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not supported.", messageNumber), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateShouldThrowSshExceptionWhenMessageDoesNotExist_WithinMessageNumberRange()
|
||||
{
|
||||
const byte messageNumber = 5;
|
||||
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.Create(messageNumber);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not supported.", messageNumber), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateShouldThrowSshExceptionWhenMessageIsNotActivated()
|
||||
{
|
||||
const byte messageNumber = 60;
|
||||
const string messageName = "SSH_MSG_USERAUTH_PASSWD_CHANGEREQ";
|
||||
|
||||
_sshMessageFactory.EnableAndActivateMessage(messageName);
|
||||
_sshMessageFactory.DisableAndDeactivateMessage(messageName);
|
||||
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.Create(messageNumber);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid in the current context.", messageNumber), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateShouldReturnMessageInstanceCorrespondingToMessageNumberWhenMessageIsEnabledAndActivated()
|
||||
{
|
||||
const byte messageNumber = 60;
|
||||
const string messageName = "SSH_MSG_USERAUTH_PASSWD_CHANGEREQ";
|
||||
|
||||
_sshMessageFactory.EnableAndActivateMessage(messageName);
|
||||
|
||||
var actual = _sshMessageFactory.Create(messageNumber);
|
||||
|
||||
Assert.IsNotNull(actual);
|
||||
Assert.AreEqual(typeof (PasswordChangeRequiredMessage), actual.GetType());
|
||||
|
||||
_sshMessageFactory.DisableAndDeactivateMessage(messageName);
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_INFO_REQUEST");
|
||||
|
||||
actual = _sshMessageFactory.Create(messageNumber);
|
||||
|
||||
Assert.IsNotNull(actual);
|
||||
Assert.AreEqual(typeof(InformationRequestMessage), actual.GetType());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DisableAndDeactivateMessageShouldThrowSshExceptionWhenAnotherMessageWithSameMessageNumberIsEnabled()
|
||||
{
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.DisableAndDeactivateMessage("SSH_MSG_USERAUTH_INFO_REQUEST");
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("Cannot enable message 'SSH_MSG_USERAUTH_INFO_REQUEST'. Message type 60 is already enabled for 'SSH_MSG_USERAUTH_PASSWD_CHANGEREQ'.", ex.Message);
|
||||
}
|
||||
|
||||
// verify that the original message remains enabled
|
||||
var actual = _sshMessageFactory.Create(60);
|
||||
Assert.IsNotNull(actual);
|
||||
Assert.AreEqual(typeof(PasswordChangeRequiredMessage), actual.GetType());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DisableAndDeactivateMessageShouldNotThrowExceptionWhenMessageIsAlreadyDisabled()
|
||||
{
|
||||
const byte messageNumber = 60;
|
||||
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
_sshMessageFactory.DisableAndDeactivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
_sshMessageFactory.DisableAndDeactivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
|
||||
// verify that message remains disabled
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.Create(messageNumber);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid in the current context.", messageNumber), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DisableAndDeactivateMessageShouldNotThrowExceptionWhenMessageWasNeverEnabled()
|
||||
{
|
||||
const byte messageNumber = 60;
|
||||
|
||||
_sshMessageFactory.DisableAndDeactivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
|
||||
// verify that message is disabled
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.Create(messageNumber);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid in the current context.", messageNumber), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DisableAndDeactivateMessageShouldThrowSshExceptionWhenMessageIsNotSupported()
|
||||
{
|
||||
const string messageName = "WHATEVER";
|
||||
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.DisableAndDeactivateMessage("WHATEVER");
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual(string.Format("Message '{0}' is not supported.", messageName), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DisableAndDeactivateMessageShouldThrowArgumentNullExceptionWhenMessageNameIsNull()
|
||||
{
|
||||
const string messageName = null;
|
||||
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.DisableAndDeactivateMessage(messageName);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ArgumentNullException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("messageName", ex.ParamName);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void EnableAndActivateMessageShouldThrowSshExceptionWhenAnotherMessageWithSameMessageNumberIsAlreadyEnabled()
|
||||
{
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_INFO_REQUEST");
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("Cannot enable message 'SSH_MSG_USERAUTH_INFO_REQUEST'. Message type 60 is already enabled for 'SSH_MSG_USERAUTH_PASSWD_CHANGEREQ'.", ex.Message);
|
||||
}
|
||||
|
||||
// verify that the original message remains enabled
|
||||
var actual = _sshMessageFactory.Create(60);
|
||||
Assert.IsNotNull(actual);
|
||||
Assert.AreEqual(typeof(PasswordChangeRequiredMessage), actual.GetType());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void EnableAndActivateMessageShouldNotThrowExceptionWhenMessageIsAlreadyEnabled()
|
||||
{
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
|
||||
var actual = _sshMessageFactory.Create(60);
|
||||
Assert.IsNotNull(actual);
|
||||
Assert.AreEqual(typeof(PasswordChangeRequiredMessage), actual.GetType());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void EnableAndActivateMessageShouldThrowSshExceptionWhenMessageIsNotSupported()
|
||||
{
|
||||
const string messageName = "WHATEVER";
|
||||
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.EnableAndActivateMessage("WHATEVER");
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual(string.Format("Message '{0}' is not supported.", messageName), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void EnableAndActivateMessageShouldThrowArgumentNullExceptionWhenMessageNameIsNull()
|
||||
{
|
||||
const string messageName = null;
|
||||
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.EnableAndActivateMessage(messageName);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ArgumentNullException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("messageName", ex.ParamName);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DisableNonKeyExchangeMessagesShouldDisableNonKeyExchangeMessages()
|
||||
{
|
||||
const byte messageNumber = 60;
|
||||
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
_sshMessageFactory.DisableNonKeyExchangeMessages();
|
||||
|
||||
// verify that message is disabled
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.Create(messageNumber);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid in the current context.", messageNumber), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DisableNonKeyExchangeMessagesShouldNotDisableKeyExchangeMessages()
|
||||
{
|
||||
const byte messageNumber = 21;
|
||||
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_NEWKEYS");
|
||||
_sshMessageFactory.DisableNonKeyExchangeMessages();
|
||||
|
||||
// verify that message remains enabled
|
||||
var actual = _sshMessageFactory.Create(messageNumber);
|
||||
Assert.IsNotNull(actual);
|
||||
Assert.AreEqual(typeof (NewKeysMessage), actual.GetType());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void EnableActivatedMessagesShouldEnableMessagesThatWereEnabledPriorToInvokingDisableNonKeyExchangeMessages()
|
||||
{
|
||||
const byte messageNumber = 60;
|
||||
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
_sshMessageFactory.DisableNonKeyExchangeMessages();
|
||||
_sshMessageFactory.EnableActivatedMessages();
|
||||
|
||||
var actual = _sshMessageFactory.Create(messageNumber);
|
||||
Assert.IsNotNull(actual);
|
||||
Assert.AreEqual(typeof(PasswordChangeRequiredMessage), actual.GetType());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void EnableActivatedMessagesShouldNotEnableMessagesThatWereDisabledPriorToInvokingDisableNonKeyExchangeMessages()
|
||||
{
|
||||
const byte messageNumber = 60;
|
||||
|
||||
_sshMessageFactory.DisableNonKeyExchangeMessages();
|
||||
_sshMessageFactory.EnableActivatedMessages();
|
||||
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.Create(messageNumber);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid in the current context.", messageNumber), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void EnableActivatedMessagesShouldNotEnableMessagesThatWereDisabledAfterInvokingDisableNonKeyExchangeMessages()
|
||||
{
|
||||
const byte messageNumber = 60;
|
||||
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
_sshMessageFactory.DisableNonKeyExchangeMessages();
|
||||
_sshMessageFactory.DisableAndDeactivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
_sshMessageFactory.EnableActivatedMessages();
|
||||
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.Create(messageNumber);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid in the current context.", messageNumber), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void EnableActivatedMessagesShouldThrowSshExceptionWhenAnothersMessageWithSameMessageNumberWasEnabledAfterInvokingDisableNonKeyExchangeMessages()
|
||||
{
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
_sshMessageFactory.DisableNonKeyExchangeMessages();
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_INFO_REQUEST");
|
||||
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.EnableActivatedMessages();
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("Cannot enable message 'SSH_MSG_USERAUTH_PASSWD_CHANGEREQ'. Message type 60 is already enabled for 'SSH_MSG_USERAUTH_INFO_REQUEST'.", ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void EnableActivatedMessagesShouldLeaveMessagesEnabledThatWereEnabledAfterInvokingDisableNonKeyExchangeMessages()
|
||||
{
|
||||
const byte messageNumber = 60;
|
||||
|
||||
_sshMessageFactory.DisableNonKeyExchangeMessages();
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
_sshMessageFactory.EnableActivatedMessages();
|
||||
|
||||
var actual = _sshMessageFactory.Create(messageNumber);
|
||||
Assert.IsNotNull(actual);
|
||||
Assert.AreEqual(typeof(PasswordChangeRequiredMessage), actual.GetType());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void HighestMessageNumberShouldCorrespondWithHighestSupportedMessageNumber()
|
||||
{
|
||||
var highestSupportMessageNumber = SshMessageFactory.AllMessages.Max(m => m.Number);
|
||||
|
||||
Assert.AreEqual(highestSupportMessageNumber, SshMessageFactory.HighestMessageNumber);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TotalMessageCountShouldBeTotalNumberOfSupportedMessages()
|
||||
{
|
||||
var totalNumberOfSupportedMessages = SshMessageFactory.AllMessages.Length;
|
||||
|
||||
Assert.AreEqual(totalNumberOfSupportedMessages, SshMessageFactory.TotalMessageCount);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestCategory("Performance")]
|
||||
public void Performance_Ctor()
|
||||
{
|
||||
const int runCount = 100000;
|
||||
|
||||
// warm-up
|
||||
for (var i = 0; i < 3; i++)
|
||||
{
|
||||
var sshMessageFactory = new SshMessageFactory();
|
||||
var sshMessageFactoryOriginal = new SshMessageFactoryOriginal();
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
var stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
|
||||
for (var i = 0; i < runCount; i++)
|
||||
{
|
||||
var sshMessageFactory = new SshMessageFactory();
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
Console.WriteLine(stopwatch.ElapsedMilliseconds);
|
||||
|
||||
stopwatch.Reset();
|
||||
stopwatch.Start();
|
||||
|
||||
for (var i = 0; i < runCount; i++)
|
||||
{
|
||||
var sshMessageFactory = new SshMessageFactoryOriginal();
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
Console.WriteLine(stopwatch.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestCategory("LongRunning")]
|
||||
[TestCategory("Performance")]
|
||||
public void Performance_Create()
|
||||
{
|
||||
const int runCount = 10000000;
|
||||
const string messageName = "SSH_MSG_CHANNEL_CLOSE";
|
||||
|
||||
_sshMessageFactory.EnableAndActivateMessage(messageName);
|
||||
_sshMessageFactoryOriginal.EnableAndActivateMessage(messageName);
|
||||
|
||||
// warm-up
|
||||
for (var i = 0; i < 3; i++)
|
||||
{
|
||||
_sshMessageFactory.Create(97);
|
||||
_sshMessageFactoryOriginal.Create(97);
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
var stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
|
||||
for (var i = 0; i < runCount; i++)
|
||||
{
|
||||
var msg = _sshMessageFactory.Create(97);
|
||||
if (msg == null)
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
Console.WriteLine(stopwatch.ElapsedMilliseconds);
|
||||
|
||||
stopwatch.Reset();
|
||||
stopwatch.Start();
|
||||
|
||||
for (var i = 0; i < runCount; i++)
|
||||
{
|
||||
var msg = _sshMessageFactoryOriginal.Create(97);
|
||||
if (msg == null)
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
Console.WriteLine(stopwatch.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestCategory("LongRunning")]
|
||||
[TestCategory("Performance")]
|
||||
public void Performance_EnableAndActivateMessage()
|
||||
{
|
||||
const int runCount = 1000000;
|
||||
const string messageName = "SSH_MSG_CHANNEL_CLOSE";
|
||||
|
||||
// warm-up
|
||||
for (var i = 0; i < 3; i++)
|
||||
{
|
||||
_sshMessageFactory.EnableAndActivateMessage(messageName);
|
||||
_sshMessageFactoryOriginal.EnableAndActivateMessage(messageName);
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
var stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
|
||||
for (var i = 0; i < runCount; i++)
|
||||
_sshMessageFactory.EnableAndActivateMessage(messageName);
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
Console.WriteLine(stopwatch.ElapsedMilliseconds);
|
||||
|
||||
stopwatch.Reset();
|
||||
stopwatch.Start();
|
||||
|
||||
for (var i = 0; i < runCount; i++)
|
||||
_sshMessageFactoryOriginal.EnableAndActivateMessage(messageName);
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
Console.WriteLine(stopwatch.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestCategory("LongRunning")]
|
||||
[TestCategory("Performance")]
|
||||
public void Performance_DisableAndDeactivateMessage()
|
||||
{
|
||||
const int runCount = 1000000;
|
||||
const string messageName = "SSH_MSG_CHANNEL_CLOSE";
|
||||
|
||||
// warm-up
|
||||
for (var i = 0; i < 3; i++)
|
||||
{
|
||||
_sshMessageFactory.DisableAndDeactivateMessage(messageName);
|
||||
_sshMessageFactoryOriginal.DisableAndDeactivateMessage(messageName);
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
var stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
|
||||
for (var i = 0; i < runCount; i++)
|
||||
_sshMessageFactory.DisableAndDeactivateMessage(messageName);
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
Console.WriteLine(stopwatch.ElapsedMilliseconds);
|
||||
|
||||
stopwatch.Reset();
|
||||
stopwatch.Start();
|
||||
|
||||
for (var i = 0; i < runCount; i++)
|
||||
_sshMessageFactoryOriginal.DisableAndDeactivateMessage(messageName);
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
Console.WriteLine(stopwatch.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestCategory("LongRunning")]
|
||||
[TestCategory("Performance")]
|
||||
public void Performance_DisableNonKeyExchangeMessages()
|
||||
{
|
||||
const int runCount = 1000000;
|
||||
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_BANNER");
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_DEBUG");
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_UNIMPLEMENTED");
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_SERVICE_ACCEPT");
|
||||
|
||||
_sshMessageFactoryOriginal.EnableAndActivateMessage("SSH_MSG_USERAUTH_BANNER");
|
||||
_sshMessageFactoryOriginal.EnableAndActivateMessage("SSH_MSG_DEBUG");
|
||||
_sshMessageFactoryOriginal.EnableAndActivateMessage("SSH_MSG_UNIMPLEMENTED");
|
||||
_sshMessageFactoryOriginal.EnableAndActivateMessage("SSH_MSG_SERVICE_ACCEPT");
|
||||
|
||||
// warm-up
|
||||
for (var i = 0; i < 3; i++)
|
||||
{
|
||||
_sshMessageFactory.DisableNonKeyExchangeMessages();
|
||||
_sshMessageFactory.EnableActivatedMessages();
|
||||
|
||||
_sshMessageFactoryOriginal.DisableNonKeyExchangeMessages();
|
||||
_sshMessageFactoryOriginal.EnableActivatedMessages();
|
||||
}
|
||||
|
||||
//Console.WriteLine("Starting test");
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
var stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
|
||||
for (var i = 0; i < runCount; i++)
|
||||
{
|
||||
_sshMessageFactory.DisableNonKeyExchangeMessages();
|
||||
_sshMessageFactory.EnableActivatedMessages();
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
Console.WriteLine(stopwatch.ElapsedMilliseconds);
|
||||
|
||||
stopwatch.Reset();
|
||||
stopwatch.Start();
|
||||
|
||||
for (var i = 0; i < runCount; i++)
|
||||
{
|
||||
_sshMessageFactoryOriginal.DisableNonKeyExchangeMessages();
|
||||
_sshMessageFactoryOriginal.EnableActivatedMessages();
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
Console.WriteLine(stopwatch.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
internal class SshMessageFactoryOriginal
|
||||
{
|
||||
private readonly IEnumerable<MessageMetadata> _messagesMetadata;
|
||||
|
||||
public SshMessageFactoryOriginal()
|
||||
{
|
||||
_messagesMetadata = new[]
|
||||
{
|
||||
new MessageMetadata {Name = "SSH_MSG_NEWKEYS", Number = 21, Type = typeof(NewKeysMessage)},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_REQUEST_FAILURE",
|
||||
Number = 82,
|
||||
Type = typeof(RequestFailureMessage)
|
||||
},
|
||||
new MessageMetadata {Name = "SSH_MSG_KEXINIT", Number = 20, Type = typeof(KeyExchangeInitMessage)},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_CHANNEL_OPEN_FAILURE",
|
||||
Number = 92,
|
||||
Type = typeof(ChannelOpenFailureMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_CHANNEL_FAILURE",
|
||||
Number = 100,
|
||||
Type = typeof(ChannelFailureMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_CHANNEL_EXTENDED_DATA",
|
||||
Number = 95,
|
||||
Type = typeof(ChannelExtendedDataMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_CHANNEL_DATA",
|
||||
Number = 94,
|
||||
Type = typeof(ChannelDataMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_USERAUTH_REQUEST",
|
||||
Number = 50,
|
||||
Type = typeof(RequestMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_CHANNEL_REQUEST",
|
||||
Number = 98,
|
||||
Type = typeof(ChannelRequestMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_USERAUTH_BANNER",
|
||||
Number = 53,
|
||||
Type = typeof(BannerMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_USERAUTH_INFO_RESPONSE",
|
||||
Number = 61,
|
||||
Type = typeof(InformationResponseMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_USERAUTH_FAILURE",
|
||||
Number = 51,
|
||||
Type = typeof(FailureMessage)
|
||||
},
|
||||
new MessageMetadata {Name = "SSH_MSG_DEBUG", Number = 4, Type = typeof(DebugMessage),},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_KEXDH_INIT",
|
||||
Number = 30,
|
||||
Type = typeof(KeyExchangeDhInitMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_GLOBAL_REQUEST",
|
||||
Number = 80,
|
||||
Type = typeof(GlobalRequestMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_CHANNEL_OPEN",
|
||||
Number = 90,
|
||||
Type = typeof(ChannelOpenMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_CHANNEL_OPEN_CONFIRMATION",
|
||||
Number = 91,
|
||||
Type = typeof(ChannelOpenConfirmationMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_USERAUTH_INFO_REQUEST",
|
||||
Number = 60,
|
||||
Type = typeof(InformationRequestMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_UNIMPLEMENTED",
|
||||
Number = 3,
|
||||
Type = typeof(UnimplementedMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_REQUEST_SUCCESS",
|
||||
Number = 81,
|
||||
Type = typeof(RequestSuccessMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_CHANNEL_SUCCESS",
|
||||
Number = 99,
|
||||
Type = typeof(ChannelSuccessMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_USERAUTH_PASSWD_CHANGEREQ",
|
||||
Number = 60,
|
||||
Type = typeof(PasswordChangeRequiredMessage)
|
||||
},
|
||||
new MessageMetadata {Name = "SSH_MSG_DISCONNECT", Number = 1, Type = typeof(DisconnectMessage)},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_SERVICE_REQUEST",
|
||||
Number = 5,
|
||||
Type = typeof(ServiceRequestMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_KEX_DH_GEX_REQUEST",
|
||||
Number = 34,
|
||||
Type = typeof(KeyExchangeDhGroupExchangeRequest)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_KEX_DH_GEX_GROUP",
|
||||
Number = 31,
|
||||
Type = typeof(KeyExchangeDhGroupExchangeGroup)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_USERAUTH_SUCCESS",
|
||||
Number = 52,
|
||||
Type = typeof(SuccessMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_USERAUTH_PK_OK",
|
||||
Number = 60,
|
||||
Type = typeof(PublicKeyMessage)
|
||||
},
|
||||
new MessageMetadata {Name = "SSH_MSG_IGNORE", Number = 2, Type = typeof(IgnoreMessage)},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_CHANNEL_WINDOW_ADJUST",
|
||||
Number = 93,
|
||||
Type = typeof(ChannelWindowAdjustMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_CHANNEL_EOF",
|
||||
Number = 96,
|
||||
Type = typeof(ChannelEofMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_CHANNEL_CLOSE",
|
||||
Number = 97,
|
||||
Type = typeof(ChannelCloseMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_SERVICE_ACCEPT",
|
||||
Number = 6,
|
||||
Type = typeof(ServiceAcceptMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_KEXDH_REPLY",
|
||||
Number = 31,
|
||||
Type = typeof(KeyExchangeDhReplyMessage)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_KEX_DH_GEX_INIT",
|
||||
Number = 32,
|
||||
Type = typeof(KeyExchangeDhGroupExchangeInit)
|
||||
},
|
||||
new MessageMetadata
|
||||
{
|
||||
Name = "SSH_MSG_KEX_DH_GEX_REPLY",
|
||||
Number = 33,
|
||||
Type = typeof(KeyExchangeDhGroupExchangeReply)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disables and deactivate all messages.
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
foreach (var messageMetadata in _messagesMetadata)
|
||||
{
|
||||
messageMetadata.Activated = messageMetadata.Enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void EnableActivatedMessages()
|
||||
{
|
||||
foreach (var messageMetadata in _messagesMetadata)
|
||||
{
|
||||
if (messageMetadata.Activated)
|
||||
messageMetadata.Enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
public Message Create(byte messageNumber)
|
||||
{
|
||||
var messageMetadata =
|
||||
(from m in _messagesMetadata where m.Number == messageNumber && m.Enabled && m.Activated select m)
|
||||
.FirstOrDefault();
|
||||
if (messageMetadata == null)
|
||||
throw new SshException(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid.",
|
||||
messageNumber));
|
||||
|
||||
return messageMetadata.Type.CreateInstance<Message>();
|
||||
}
|
||||
|
||||
public void DisableNonKeyExchangeMessages()
|
||||
{
|
||||
foreach (var messageMetadata in _messagesMetadata)
|
||||
{
|
||||
if (messageMetadata.Activated && messageMetadata.Number > 2 &&
|
||||
(messageMetadata.Number < 20 || messageMetadata.Number > 30))
|
||||
{
|
||||
//Console.WriteLine("Disabling " + messageMetadata.Name + "...");
|
||||
|
||||
messageMetadata.Enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void EnableAndActivateMessage(string messageName)
|
||||
{
|
||||
lock (_messagesMetadata)
|
||||
{
|
||||
var messagesMetadata = _messagesMetadata.Where(m => m.Name == messageName);
|
||||
foreach (var messageMetadata in messagesMetadata)
|
||||
messageMetadata.Enabled = messageMetadata.Activated = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void DisableAndDeactivateMessage(string messageName)
|
||||
{
|
||||
lock (_messagesMetadata)
|
||||
{
|
||||
var messagesMetadata = _messagesMetadata.Where(m => m.Name == messageName);
|
||||
foreach (var messageMetadata in messagesMetadata)
|
||||
messageMetadata.Enabled = messageMetadata.Activated = false;
|
||||
}
|
||||
}
|
||||
|
||||
private class MessageMetadata
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public byte Number { get; set; }
|
||||
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
public bool Activated { get; set; }
|
||||
|
||||
public Type Type { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
using Renci.SshNet.Abstractions;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class AbstractionsTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void SocketAbstraction_CanWrite_ShouldReturnFalseWhenSocketIsNull()
|
||||
{
|
||||
Assert.IsFalse(SocketAbstraction.CanWrite(null));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CryptoAbstraction_GenerateRandom_ShouldPerformNoOpWhenDataIsZeroLength()
|
||||
{
|
||||
Assert.AreEqual(0, CryptoAbstraction.GenerateRandom(0).Length);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CryptoAbstraction_GenerateRandom_ShouldGenerateRandomSequenceOfValues()
|
||||
{
|
||||
var dataLength = new Random().Next(1, 100);
|
||||
|
||||
var dataA = CryptoAbstraction.GenerateRandom(dataLength);
|
||||
var dataB = CryptoAbstraction.GenerateRandom(dataLength);
|
||||
|
||||
Assert.AreEqual(dataLength, dataA.Length);
|
||||
Assert.AreEqual(dataLength, dataB.Length);
|
||||
|
||||
CollectionAssert.AreNotEqual(dataA, dataB);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ThreadAbstraction_ExecuteThread_ShouldThrowArgumentNullExceptionWhenActionIsNull()
|
||||
{
|
||||
var ex = Assert.ThrowsException<ArgumentNullException>(() => ThreadAbstraction.ExecuteThread(null));
|
||||
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("action", ex.ParamName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ThreadAbstraction_ExecuteThread_ShouldExecuteActionOnSeparateThread()
|
||||
{
|
||||
int threadId = 0;
|
||||
using var waitHandle = new ManualResetEventSlim();
|
||||
|
||||
ThreadAbstraction.ExecuteThread(() =>
|
||||
{
|
||||
threadId = Environment.CurrentManagedThreadId;
|
||||
waitHandle.Set();
|
||||
});
|
||||
|
||||
Assert.IsTrue(waitHandle.Wait(1000));
|
||||
Assert.AreNotEqual(0, threadId);
|
||||
Assert.AreNotEqual(Environment.CurrentManagedThreadId, threadId);
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Renci.SshNet.Tests
|
||||
#pragma warning disable SA1131 // Use readable conditions
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class ForwardedPortStatusTest_Started
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Renci.SshNet.Tests
|
||||
#pragma warning disable SA1131 // Use readable conditions
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class ForwardedPortStatusTest_Starting
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Renci.SshNet.Tests
|
||||
#pragma warning disable SA1131 // Use readable conditions
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class ForwardedPortStatusTest_Stopped
|
||||
+3
-1
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Renci.SshNet.Tests
|
||||
#pragma warning disable SA1131 // Use readable conditions
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class ForwardedPortStatusTest_Stopping
|
||||
@@ -0,0 +1,423 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Messages.Authentication;
|
||||
using Renci.SshNet.Messages.Transport;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class SshMessageFactoryTest
|
||||
{
|
||||
private SshMessageFactory _sshMessageFactory;
|
||||
|
||||
[TestInitialize]
|
||||
public void SetUp()
|
||||
{
|
||||
_sshMessageFactory = new SshMessageFactory();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateShouldThrowSshExceptionWhenMessageIsNotEnabled()
|
||||
{
|
||||
const byte messageNumber = 60;
|
||||
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.Create(messageNumber);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid in the current context.", messageNumber), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateShouldThrowSshExceptionWhenMessageDoesNotExist_OutsideOfMessageNumberRange()
|
||||
{
|
||||
const byte messageNumber = 255;
|
||||
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.Create(messageNumber);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not supported.", messageNumber), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateShouldThrowSshExceptionWhenMessageDoesNotExist_WithinMessageNumberRange()
|
||||
{
|
||||
const byte messageNumber = 5;
|
||||
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.Create(messageNumber);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not supported.", messageNumber), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateShouldThrowSshExceptionWhenMessageIsNotActivated()
|
||||
{
|
||||
const byte messageNumber = 60;
|
||||
const string messageName = "SSH_MSG_USERAUTH_PASSWD_CHANGEREQ";
|
||||
|
||||
_sshMessageFactory.EnableAndActivateMessage(messageName);
|
||||
_sshMessageFactory.DisableAndDeactivateMessage(messageName);
|
||||
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.Create(messageNumber);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid in the current context.", messageNumber), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateShouldReturnMessageInstanceCorrespondingToMessageNumberWhenMessageIsEnabledAndActivated()
|
||||
{
|
||||
const byte messageNumber = 60;
|
||||
const string messageName = "SSH_MSG_USERAUTH_PASSWD_CHANGEREQ";
|
||||
|
||||
_sshMessageFactory.EnableAndActivateMessage(messageName);
|
||||
|
||||
var actual = _sshMessageFactory.Create(messageNumber);
|
||||
|
||||
Assert.IsNotNull(actual);
|
||||
Assert.AreEqual(typeof(PasswordChangeRequiredMessage), actual.GetType());
|
||||
|
||||
_sshMessageFactory.DisableAndDeactivateMessage(messageName);
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_INFO_REQUEST");
|
||||
|
||||
actual = _sshMessageFactory.Create(messageNumber);
|
||||
|
||||
Assert.IsNotNull(actual);
|
||||
Assert.AreEqual(typeof(InformationRequestMessage), actual.GetType());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DisableAndDeactivateMessageShouldThrowSshExceptionWhenAnotherMessageWithSameMessageNumberIsEnabled()
|
||||
{
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.DisableAndDeactivateMessage("SSH_MSG_USERAUTH_INFO_REQUEST");
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("Cannot enable message 'SSH_MSG_USERAUTH_INFO_REQUEST'. Message type 60 is already enabled for 'SSH_MSG_USERAUTH_PASSWD_CHANGEREQ'.", ex.Message);
|
||||
}
|
||||
|
||||
// verify that the original message remains enabled
|
||||
var actual = _sshMessageFactory.Create(60);
|
||||
Assert.IsNotNull(actual);
|
||||
Assert.AreEqual(typeof(PasswordChangeRequiredMessage), actual.GetType());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DisableAndDeactivateMessageShouldNotThrowExceptionWhenMessageIsAlreadyDisabled()
|
||||
{
|
||||
const byte messageNumber = 60;
|
||||
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
_sshMessageFactory.DisableAndDeactivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
_sshMessageFactory.DisableAndDeactivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
|
||||
// verify that message remains disabled
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.Create(messageNumber);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid in the current context.", messageNumber), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DisableAndDeactivateMessageShouldNotThrowExceptionWhenMessageWasNeverEnabled()
|
||||
{
|
||||
const byte messageNumber = 60;
|
||||
|
||||
_sshMessageFactory.DisableAndDeactivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
|
||||
// verify that message is disabled
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.Create(messageNumber);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid in the current context.", messageNumber), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DisableAndDeactivateMessageShouldThrowSshExceptionWhenMessageIsNotSupported()
|
||||
{
|
||||
const string messageName = "WHATEVER";
|
||||
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.DisableAndDeactivateMessage("WHATEVER");
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual(string.Format("Message '{0}' is not supported.", messageName), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DisableAndDeactivateMessageShouldThrowArgumentNullExceptionWhenMessageNameIsNull()
|
||||
{
|
||||
const string messageName = null;
|
||||
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.DisableAndDeactivateMessage(messageName);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ArgumentNullException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("messageName", ex.ParamName);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void EnableAndActivateMessageShouldThrowSshExceptionWhenAnotherMessageWithSameMessageNumberIsAlreadyEnabled()
|
||||
{
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_INFO_REQUEST");
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("Cannot enable message 'SSH_MSG_USERAUTH_INFO_REQUEST'. Message type 60 is already enabled for 'SSH_MSG_USERAUTH_PASSWD_CHANGEREQ'.", ex.Message);
|
||||
}
|
||||
|
||||
// verify that the original message remains enabled
|
||||
var actual = _sshMessageFactory.Create(60);
|
||||
Assert.IsNotNull(actual);
|
||||
Assert.AreEqual(typeof(PasswordChangeRequiredMessage), actual.GetType());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void EnableAndActivateMessageShouldNotThrowExceptionWhenMessageIsAlreadyEnabled()
|
||||
{
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
|
||||
var actual = _sshMessageFactory.Create(60);
|
||||
Assert.IsNotNull(actual);
|
||||
Assert.AreEqual(typeof(PasswordChangeRequiredMessage), actual.GetType());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void EnableAndActivateMessageShouldThrowSshExceptionWhenMessageIsNotSupported()
|
||||
{
|
||||
const string messageName = "WHATEVER";
|
||||
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.EnableAndActivateMessage("WHATEVER");
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual(string.Format("Message '{0}' is not supported.", messageName), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void EnableAndActivateMessageShouldThrowArgumentNullExceptionWhenMessageNameIsNull()
|
||||
{
|
||||
const string messageName = null;
|
||||
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.EnableAndActivateMessage(messageName);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ArgumentNullException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("messageName", ex.ParamName);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DisableNonKeyExchangeMessagesShouldDisableNonKeyExchangeMessages()
|
||||
{
|
||||
const byte messageNumber = 60;
|
||||
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
_sshMessageFactory.DisableNonKeyExchangeMessages(strict: false);
|
||||
|
||||
// verify that message is disabled
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.Create(messageNumber);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid in the current context.", messageNumber), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DisableNonKeyExchangeMessagesShouldNotDisableKeyExchangeMessages()
|
||||
{
|
||||
const byte messageNumber = 21;
|
||||
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_NEWKEYS");
|
||||
_sshMessageFactory.DisableNonKeyExchangeMessages(strict: false);
|
||||
|
||||
// verify that message remains enabled
|
||||
var actual = _sshMessageFactory.Create(messageNumber);
|
||||
Assert.IsNotNull(actual);
|
||||
Assert.AreEqual(typeof(NewKeysMessage), actual.GetType());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void EnableActivatedMessagesShouldEnableMessagesThatWereEnabledPriorToInvokingDisableNonKeyExchangeMessages()
|
||||
{
|
||||
const byte messageNumber = 60;
|
||||
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
_sshMessageFactory.DisableNonKeyExchangeMessages(strict: false);
|
||||
_sshMessageFactory.EnableActivatedMessages();
|
||||
|
||||
var actual = _sshMessageFactory.Create(messageNumber);
|
||||
Assert.IsNotNull(actual);
|
||||
Assert.AreEqual(typeof(PasswordChangeRequiredMessage), actual.GetType());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void EnableActivatedMessagesShouldNotEnableMessagesThatWereDisabledPriorToInvokingDisableNonKeyExchangeMessages()
|
||||
{
|
||||
const byte messageNumber = 60;
|
||||
|
||||
_sshMessageFactory.DisableNonKeyExchangeMessages(strict: false);
|
||||
_sshMessageFactory.EnableActivatedMessages();
|
||||
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.Create(messageNumber);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid in the current context.", messageNumber), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void EnableActivatedMessagesShouldNotEnableMessagesThatWereDisabledAfterInvokingDisableNonKeyExchangeMessages()
|
||||
{
|
||||
const byte messageNumber = 60;
|
||||
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
_sshMessageFactory.DisableNonKeyExchangeMessages(strict: false);
|
||||
_sshMessageFactory.DisableAndDeactivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
_sshMessageFactory.EnableActivatedMessages();
|
||||
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.Create(messageNumber);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid in the current context.", messageNumber), ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void EnableActivatedMessagesShouldThrowSshExceptionWhenAnothersMessageWithSameMessageNumberWasEnabledAfterInvokingDisableNonKeyExchangeMessages()
|
||||
{
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
_sshMessageFactory.DisableNonKeyExchangeMessages(strict: false);
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_INFO_REQUEST");
|
||||
|
||||
try
|
||||
{
|
||||
_sshMessageFactory.EnableActivatedMessages();
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (SshException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("Cannot enable message 'SSH_MSG_USERAUTH_PASSWD_CHANGEREQ'. Message type 60 is already enabled for 'SSH_MSG_USERAUTH_INFO_REQUEST'.", ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void EnableActivatedMessagesShouldLeaveMessagesEnabledThatWereEnabledAfterInvokingDisableNonKeyExchangeMessages()
|
||||
{
|
||||
const byte messageNumber = 60;
|
||||
|
||||
_sshMessageFactory.DisableNonKeyExchangeMessages(strict: false);
|
||||
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
|
||||
_sshMessageFactory.EnableActivatedMessages();
|
||||
|
||||
var actual = _sshMessageFactory.Create(messageNumber);
|
||||
Assert.IsNotNull(actual);
|
||||
Assert.AreEqual(typeof(PasswordChangeRequiredMessage), actual.GetType());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void HighestMessageNumberShouldCorrespondWithHighestSupportedMessageNumber()
|
||||
{
|
||||
var highestSupportMessageNumber = SshMessageFactory.AllMessages.Max(m => m.Number);
|
||||
|
||||
Assert.AreEqual(highestSupportMessageNumber, SshMessageFactory.HighestMessageNumber);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TotalMessageCountShouldBeTotalNumberOfSupportedMessages()
|
||||
{
|
||||
var totalNumberOfSupportedMessages = SshMessageFactory.AllMessages.Length;
|
||||
|
||||
Assert.AreEqual(totalNumberOfSupportedMessages, SshMessageFactory.TotalMessageCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,179 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet.Tests.Common
|
||||
{
|
||||
public class HttpProxyStub : IDisposable
|
||||
{
|
||||
private readonly IPEndPoint _endPoint;
|
||||
private AsyncSocketListener _listener;
|
||||
private HttpRequestParser _httpRequestParser;
|
||||
private readonly IList<byte[]> _responses;
|
||||
|
||||
public HttpProxyStub(IPEndPoint endPoint)
|
||||
{
|
||||
_endPoint = endPoint;
|
||||
_responses = new List<byte[]>();
|
||||
}
|
||||
|
||||
public HttpRequest HttpRequest
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_httpRequestParser == null)
|
||||
{
|
||||
throw new InvalidOperationException("The proxy is not started.");
|
||||
}
|
||||
|
||||
return _httpRequestParser.HttpRequest;
|
||||
}
|
||||
}
|
||||
|
||||
public IList<byte[]> Responses
|
||||
{
|
||||
get { return _responses; }
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
_httpRequestParser = new HttpRequestParser();
|
||||
|
||||
_listener = new AsyncSocketListener(_endPoint);
|
||||
_listener.BytesReceived += OnBytesReceived;
|
||||
_listener.Start();
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
_listener?.Stop();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Stop();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private void OnBytesReceived(byte[] bytesReceived, Socket socket)
|
||||
{
|
||||
_httpRequestParser.ProcessData(bytesReceived);
|
||||
|
||||
if (_httpRequestParser.CurrentState == HttpRequestParser.State.Content)
|
||||
{
|
||||
foreach (var response in Responses)
|
||||
{
|
||||
_ = socket.Send(response);
|
||||
}
|
||||
|
||||
socket.Shutdown(SocketShutdown.Send);
|
||||
}
|
||||
}
|
||||
|
||||
private class HttpRequestParser
|
||||
{
|
||||
private readonly List<byte> _buffer;
|
||||
private readonly HttpRequest _httpRequest;
|
||||
|
||||
public enum State
|
||||
{
|
||||
RequestLine,
|
||||
Headers,
|
||||
Content
|
||||
}
|
||||
|
||||
public HttpRequestParser()
|
||||
{
|
||||
CurrentState = State.RequestLine;
|
||||
_buffer = new List<byte>();
|
||||
_httpRequest = new HttpRequest();
|
||||
}
|
||||
|
||||
public HttpRequest HttpRequest
|
||||
{
|
||||
get { return _httpRequest; }
|
||||
}
|
||||
|
||||
public State CurrentState { get; private set; }
|
||||
|
||||
public void ProcessData(byte[] data)
|
||||
{
|
||||
var position = 0;
|
||||
|
||||
while (position != data.Length)
|
||||
{
|
||||
if (CurrentState == State.RequestLine)
|
||||
{
|
||||
var requestLine = ReadLine(data, ref position);
|
||||
if (requestLine != null)
|
||||
{
|
||||
_httpRequest.RequestLine = requestLine;
|
||||
CurrentState = State.Headers;
|
||||
}
|
||||
}
|
||||
|
||||
if (CurrentState == State.Headers)
|
||||
{
|
||||
var line = ReadLine(data, ref position);
|
||||
if (line != null)
|
||||
{
|
||||
if (line.Length == 0)
|
||||
{
|
||||
CurrentState = State.Content;
|
||||
}
|
||||
else
|
||||
{
|
||||
_httpRequest.Headers.Add(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (CurrentState == State.Content)
|
||||
{
|
||||
if (position < data.Length)
|
||||
{
|
||||
var currentContent = _httpRequest.MessageBody;
|
||||
var newBufferSize = currentContent.Length + (data.Length - position);
|
||||
var copyBuffer = new byte[newBufferSize];
|
||||
Array.Copy(currentContent, copyBuffer, currentContent.Length);
|
||||
Array.Copy(data, position, copyBuffer, currentContent.Length, data.Length - position);
|
||||
_httpRequest.MessageBody = copyBuffer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string ReadLine(byte[] data, ref int position)
|
||||
{
|
||||
for (; position < data.Length; position++)
|
||||
{
|
||||
var b = data[position];
|
||||
if (b == '\n')
|
||||
{
|
||||
var buffer = _buffer.ToArray();
|
||||
var bytesInLine = buffer.Length;
|
||||
|
||||
// when the previous byte was a CR, then do not include it in line
|
||||
if (buffer.Length > 0 && buffer[buffer.Length - 1] == '\r')
|
||||
{
|
||||
bytesInLine -= 1;
|
||||
}
|
||||
|
||||
// clear the buffer
|
||||
_buffer.Clear();
|
||||
|
||||
// move position up one position as we've processed the current byte
|
||||
position++;
|
||||
return Encoding.ASCII.GetString(buffer, 0, bytesInLine);
|
||||
}
|
||||
_buffer.Add(b);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Renci.SshNet.Tests.Common
|
||||
{
|
||||
public class HttpRequest
|
||||
{
|
||||
public HttpRequest()
|
||||
{
|
||||
Headers = new List<string>();
|
||||
MessageBody = new byte[0];
|
||||
}
|
||||
|
||||
public string RequestLine { get; set; }
|
||||
public IList<string> Headers { get; set; }
|
||||
public byte[] MessageBody { get; set; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user