Significantly improve performance of ShellStream's Expect methods (#1207)

* Significantly improved performance and fixed bug with ShellStream's Expect methods.

* Fix whitespace.

* Fixed test.

* Improve ShellStream Expect

* Fixed typo.

* Doubled expectBuffer's default size and added a large expect test.

* Added guard clauses to ShellStream constructor and adjusted Common_CreateMoreChannelsThanMaxSessions test.

* Fixed XMLDoc spelling mistakes.

---------

Co-authored-by: Wojciech Nagórski <wojtpl2@gmail.com>
Co-authored-by: Wojciech Nagórski <wojciech.nagorski@intel.com>
This commit is contained in:
Jean-Sebastien Carle
2024-02-13 07:41:47 -05:00
committed by GitHub
parent 7d357e8203
commit bcaf354ccb
24 changed files with 253 additions and 61 deletions
+3 -1
View File
@@ -114,6 +114,7 @@ namespace Renci.SshNet
/// <param name="height">The terminal height in pixels.</param>
/// <param name="terminalModeValues">The terminal mode values.</param>
/// <param name="bufferSize">Size of the buffer.</param>
/// <param name="expectSize">Size of the expect buffer.</param>
/// <returns>
/// The created <see cref="ShellStream"/> instance.
/// </returns>
@@ -135,7 +136,8 @@ namespace Renci.SshNet
uint width,
uint height,
IDictionary<TerminalModes, uint> terminalModeValues,
int bufferSize);
int bufferSize,
int expectSize);
/// <summary>
/// Creates an <see cref="IRemotePathTransformation"/> that encloses a path in double quotes, and escapes
+4 -3
View File
@@ -187,6 +187,7 @@ namespace Renci.SshNet
/// <param name="height">The terminal height in pixels.</param>
/// <param name="terminalModeValues">The terminal mode values.</param>
/// <param name="bufferSize">The size of the buffer.</param>
/// <param name="expectSize">The size of the expect buffer.</param>
/// <returns>
/// The created <see cref="ShellStream"/> instance.
/// </returns>
@@ -194,16 +195,16 @@ namespace Renci.SshNet
/// <remarks>
/// <para>
/// The <c>TERM</c> environment variable contains an identifier for the text window's capabilities.
/// You can get a detailed list of these cababilities by using the infocmp command.
/// You can get a detailed list of these capabilities by using the infocmp command.
/// </para>
/// <para>
/// The column/row dimensions override the pixel dimensions(when non-zero). Pixel dimensions refer
/// to the drawable area of the window.
/// </para>
/// </remarks>
public ShellStream CreateShellStream(ISession session, string terminalName, uint columns, uint rows, uint width, uint height, IDictionary<TerminalModes, uint> terminalModeValues, int bufferSize)
public ShellStream CreateShellStream(ISession session, string terminalName, uint columns, uint rows, uint width, uint height, IDictionary<TerminalModes, uint> terminalModeValues, int bufferSize, int expectSize)
{
return new ShellStream(session, terminalName, columns, rows, width, height, terminalModeValues, bufferSize);
return new ShellStream(session, terminalName, columns, rows, width, height, terminalModeValues, bufferSize, expectSize);
}
/// <summary>
+79 -30
View File
@@ -22,6 +22,8 @@ namespace Renci.SshNet
private readonly Encoding _encoding;
private readonly int _bufferSize;
private readonly Queue<byte> _incoming;
private readonly int _expectSize;
private readonly Queue<byte> _expect;
private readonly Queue<byte> _outgoing;
private IChannelSession _channel;
private AutoResetEvent _dataReceived = new AutoResetEvent(initialState: false);
@@ -76,15 +78,28 @@ namespace Renci.SshNet
/// <param name="height">The terminal height in pixels.</param>
/// <param name="terminalModeValues">The terminal mode values.</param>
/// <param name="bufferSize">The size of the buffer.</param>
/// <param name="expectSize">The size of the expect buffer.</param>
/// <exception cref="SshException">The channel could not be opened.</exception>
/// <exception cref="SshException">The pseudo-terminal request was not accepted by the server.</exception>
/// <exception cref="SshException">The request to start a shell was not accepted by the server.</exception>
internal ShellStream(ISession session, string terminalName, uint columns, uint rows, uint width, uint height, IDictionary<TerminalModes, uint> terminalModeValues, int bufferSize)
internal ShellStream(ISession session, string terminalName, uint columns, uint rows, uint width, uint height, IDictionary<TerminalModes, uint> terminalModeValues, int bufferSize, int expectSize)
{
if (bufferSize <= 0)
{
throw new ArgumentException($"{nameof(bufferSize)} must be between 1 and {int.MaxValue}.");
}
if (expectSize <= 0)
{
throw new ArgumentException($"{nameof(expectSize)} must be between 1 and {int.MaxValue}.");
}
_encoding = session.ConnectionInfo.Encoding;
_session = session;
_bufferSize = bufferSize;
_incoming = new Queue<byte>();
_expectSize = expectSize;
_expect = new Queue<byte>(_expectSize);
_outgoing = new Queue<byte>();
_channel = _session.CreateChannelSession();
@@ -248,35 +263,40 @@ namespace Renci.SshNet
public void Expect(TimeSpan timeout, params ExpectAction[] expectActions)
{
var expectedFound = false;
var text = string.Empty;
var matchText = string.Empty;
do
{
lock (_incoming)
{
if (_incoming.Count > 0)
if (_expect.Count > 0)
{
text = _encoding.GetString(_incoming.ToArray(), 0, _incoming.Count);
matchText = _encoding.GetString(_expect.ToArray(), 0, _expect.Count);
}
if (text.Length > 0)
if (matchText.Length > 0)
{
foreach (var expectAction in expectActions)
{
var match = expectAction.Expect.Match(text);
var match = expectAction.Expect.Match(matchText);
if (match.Success)
{
var result = text.Substring(0, match.Index + match.Length);
var charCount = _encoding.GetByteCount(result);
var returnText = matchText.Substring(0, match.Index + match.Length);
var returnLength = _encoding.GetByteCount(returnText);
for (var i = 0; i < charCount && _incoming.Count > 0; i++)
// Remove processed items from the queue
for (var i = 0; i < returnLength && _incoming.Count > 0; i++)
{
// Remove processed items from the queue
if (_expect.Count == _incoming.Count)
{
_ = _expect.Dequeue();
}
_ = _incoming.Dequeue();
}
expectAction.Action(result);
expectAction.Action(returnText);
expectedFound = true;
}
}
@@ -349,27 +369,33 @@ namespace Renci.SshNet
/// </returns>
public string Expect(Regex regex, TimeSpan timeout)
{
var result = string.Empty;
var matchText = string.Empty;
string returnText;
while (true)
{
lock (_incoming)
{
if (_incoming.Count > 0)
if (_expect.Count > 0)
{
result = _encoding.GetString(_incoming.ToArray(), 0, _incoming.Count);
matchText = _encoding.GetString(_expect.ToArray(), 0, _expect.Count);
}
var match = regex.Match(result);
var match = regex.Match(matchText);
if (match.Success)
{
result = result.Substring(0, match.Index + match.Length);
var charCount = _encoding.GetByteCount(result);
returnText = matchText.Substring(0, match.Index + match.Length);
var returnLength = _encoding.GetByteCount(returnText);
// Remove processed items from the queue
for (var i = 0; i < charCount && _incoming.Count > 0; i++)
for (var i = 0; i < returnLength && _incoming.Count > 0; i++)
{
if (_expect.Count == _incoming.Count)
{
_ = _expect.Dequeue();
}
_ = _incoming.Dequeue();
}
@@ -390,7 +416,7 @@ namespace Renci.SshNet
}
}
return result;
return returnText;
}
/// <summary>
@@ -446,7 +472,8 @@ namespace Renci.SshNet
public IAsyncResult BeginExpect(TimeSpan timeout, AsyncCallback callback, object state, params ExpectAction[] expectActions)
#pragma warning restore CA1859 // Use concrete types when possible for improved performance
{
var text = string.Empty;
var matchText = string.Empty;
string returnText;
// Create new AsyncResult object
var asyncResult = new ExpectAsyncResult(callback, state);
@@ -461,31 +488,36 @@ namespace Renci.SshNet
{
lock (_incoming)
{
if (_incoming.Count > 0)
if (_expect.Count > 0)
{
text = _encoding.GetString(_incoming.ToArray(), 0, _incoming.Count);
matchText = _encoding.GetString(_expect.ToArray(), 0, _expect.Count);
}
if (text.Length > 0)
if (matchText.Length > 0)
{
foreach (var expectAction in expectActions)
{
var match = expectAction.Expect.Match(text);
var match = expectAction.Expect.Match(matchText);
if (match.Success)
{
var result = text.Substring(0, match.Index + match.Length);
var charCount = _encoding.GetByteCount(result);
returnText = matchText.Substring(0, match.Index + match.Length);
var returnLength = _encoding.GetByteCount(returnText);
for (var i = 0; i < match.Index + match.Length && _incoming.Count > 0; i++)
// Remove processed items from the queue
for (var i = 0; i < returnLength && _incoming.Count > 0; i++)
{
// Remove processed items from the queue
if (_expect.Count == _incoming.Count)
{
_ = _expect.Dequeue();
}
_ = _incoming.Dequeue();
}
expectAction.Action(result);
expectAction.Action(returnText);
callback?.Invoke(asyncResult);
expectActionResult = result;
expectActionResult = returnText;
}
}
}
@@ -584,6 +616,11 @@ namespace Renci.SshNet
// remove processed bytes from the queue
for (var i = 0; i < bytesProcessed; i++)
{
if (_expect.Count == _incoming.Count)
{
_ = _expect.Dequeue();
}
_ = _incoming.Dequeue();
}
@@ -620,6 +657,7 @@ namespace Renci.SshNet
lock (_incoming)
{
text = _encoding.GetString(_incoming.ToArray(), 0, _incoming.Count);
_expect.Clear();
_incoming.Clear();
}
@@ -649,6 +687,11 @@ namespace Renci.SshNet
{
for (; i < count && _incoming.Count > 0; i++)
{
if (_expect.Count == _incoming.Count)
{
_ = _expect.Dequeue();
}
buffer[offset + i] = _incoming.Dequeue();
}
}
@@ -800,6 +843,12 @@ namespace Renci.SshNet
foreach (var b in e.Data)
{
_incoming.Enqueue(b);
if (_expect.Count == _expectSize)
{
_ = _expect.Dequeue();
}
_expect.Enqueue(b);
}
}
+67 -4
View File
@@ -407,7 +407,7 @@ namespace Renci.SshNet
/// <remarks>
/// <para>
/// The <c>TERM</c> environment variable contains an identifier for the text window's capabilities.
/// You can get a detailed list of these cababilities by using the infocmp command.
/// You can get a detailed list of these capabilities by using the infocmp command.
/// </para>
/// <para>
/// The column/row dimensions override the pixel dimensions(when nonzero). Pixel dimensions refer
@@ -416,7 +416,38 @@ namespace Renci.SshNet
/// </remarks>
public ShellStream CreateShellStream(string terminalName, uint columns, uint rows, uint width, uint height, int bufferSize)
{
return CreateShellStream(terminalName, columns, rows, width, height, bufferSize, terminalModeValues: null);
return CreateShellStream(terminalName, columns, rows, width, height, bufferSize, bufferSize * 2, terminalModeValues: null);
}
/// <summary>
/// Creates the shell stream.
/// </summary>
/// <param name="terminalName">The <c>TERM</c> environment variable.</param>
/// <param name="columns">The terminal width in columns.</param>
/// <param name="rows">The terminal width in rows.</param>
/// <param name="width">The terminal width in pixels.</param>
/// <param name="height">The terminal height in pixels.</param>
/// <param name="bufferSize">The size of the buffer.</param>
/// <param name="expectSize">The size of the expect buffer.</param>
/// <returns>
/// The created <see cref="ShellStream"/> instance.
/// </returns>
/// <exception cref="SshConnectionException">Client is not connected.</exception>
/// <remarks>
/// <para>
/// The <c>TERM</c> environment variable contains an identifier for the text window's capabilities.
/// You can get a detailed list of these capabilities by using the infocmp command.
/// </para>
/// <para>
/// The column/row dimensions override the pixel dimensions(when non-zero). Pixel dimensions refer
/// to the drawable area of the window.
/// </para>
/// </remarks>
public ShellStream CreateShellStream(string terminalName, uint columns, uint rows, uint width, uint height, int bufferSize, int expectSize)
{
EnsureSessionIsOpen();
return CreateShellStream(terminalName, columns, rows, width, height, bufferSize, expectSize, terminalModeValues: null);
}
/// <summary>
@@ -436,7 +467,7 @@ namespace Renci.SshNet
/// <remarks>
/// <para>
/// The <c>TERM</c> environment variable contains an identifier for the text window's capabilities.
/// You can get a detailed list of these cababilities by using the infocmp command.
/// You can get a detailed list of these capabilities by using the infocmp command.
/// </para>
/// <para>
/// The column/row dimensions override the pixel dimensions(when non-zero). Pixel dimensions refer
@@ -447,7 +478,39 @@ namespace Renci.SshNet
{
EnsureSessionIsOpen();
return ServiceFactory.CreateShellStream(Session, terminalName, columns, rows, width, height, terminalModeValues, bufferSize);
return CreateShellStream(terminalName, columns, rows, width, height, bufferSize, bufferSize * 2, terminalModeValues);
}
/// <summary>
/// Creates the shell stream.
/// </summary>
/// <param name="terminalName">The <c>TERM</c> environment variable.</param>
/// <param name="columns">The terminal width in columns.</param>
/// <param name="rows">The terminal width in rows.</param>
/// <param name="width">The terminal width in pixels.</param>
/// <param name="height">The terminal height in pixels.</param>
/// <param name="bufferSize">The size of the buffer.</param>
/// <param name="expectSize">The size of the expect buffer.</param>
/// <param name="terminalModeValues">The terminal mode values.</param>
/// <returns>
/// The created <see cref="ShellStream"/> instance.
/// </returns>
/// <exception cref="SshConnectionException">Client is not connected.</exception>
/// <remarks>
/// <para>
/// The <c>TERM</c> environment variable contains an identifier for the text window's capabilities.
/// You can get a detailed list of these capabilities by using the infocmp command.
/// </para>
/// <para>
/// The column/row dimensions override the pixel dimensions(when non-zero). Pixel dimensions refer
/// to the drawable area of the window.
/// </para>
/// </remarks>
public ShellStream CreateShellStream(string terminalName, uint columns, uint rows, uint width, uint height, int bufferSize, int expectSize, IDictionary<TerminalModes, uint> terminalModeValues)
{
EnsureSessionIsOpen();
return ServiceFactory.CreateShellStream(Session, terminalName, columns, rows, width, height, terminalModeValues, bufferSize, expectSize);
}
/// <summary>
@@ -44,7 +44,7 @@ namespace Renci.SshNet.IntegrationTests
// if the channel would not be properly closed
for (var i = 0; i < connectionInfo.MaxSessions + 1; i++)
{
using (var stream = client.CreateShellStream("vt220", 20, 20, 20, 20, 0))
using (var stream = client.CreateShellStream("vt220", 20, 20, 20, 20, 20))
{
stream.WriteLine("echo test");
stream.ReadLine();
@@ -22,6 +22,7 @@ namespace Renci.SshNet.Tests.Classes
private uint _height;
private IDictionary<TerminalModes, uint> _terminalModeValues;
private int _bufferSize;
private int _expectSize;
private SshException _channelOpenException;
private SshException _actualException;
@@ -36,6 +37,7 @@ namespace Renci.SshNet.Tests.Classes
_height = (uint) random.Next();
_terminalModeValues = new Dictionary<TerminalModes, uint>();
_bufferSize = random.Next();
_expectSize = _bufferSize;
_channelOpenException = new SshException();
_actualException = null;
@@ -95,7 +97,8 @@ namespace Renci.SshNet.Tests.Classes
_width,
_height,
_terminalModeValues,
_bufferSize);
_bufferSize,
_expectSize);
Assert.Fail();
}
catch (SshException ex)
@@ -22,6 +22,7 @@ namespace Renci.SshNet.Tests.Classes
private uint _height;
private IDictionary<TerminalModes, uint> _terminalModeValues;
private int _bufferSize;
private int _expectSize;
private SshException _actualException;
private void SetupData()
@@ -35,6 +36,7 @@ namespace Renci.SshNet.Tests.Classes
_height = (uint)random.Next();
_terminalModeValues = new Dictionary<TerminalModes, uint>();
_bufferSize = random.Next();
_expectSize = _bufferSize;
_actualException = null;
}
@@ -94,7 +96,8 @@ namespace Renci.SshNet.Tests.Classes
_width,
_height,
_terminalModeValues,
_bufferSize);
_bufferSize,
_expectSize);
Assert.Fail();
}
catch (SshException ex)
@@ -22,6 +22,7 @@ namespace Renci.SshNet.Tests.Classes
private uint _height;
private IDictionary<TerminalModes, uint> _terminalModeValues;
private int _bufferSize;
private int _expectSize;
private SshException _sendPseudoTerminalRequestException;
private SshException _actualException;
@@ -36,6 +37,7 @@ namespace Renci.SshNet.Tests.Classes
_height = (uint) random.Next();
_terminalModeValues = new Dictionary<TerminalModes, uint>();
_bufferSize = random.Next();
_expectSize = _bufferSize;
_sendPseudoTerminalRequestException = new SshException();
_actualException = null;
@@ -97,7 +99,8 @@ namespace Renci.SshNet.Tests.Classes
_width,
_height,
_terminalModeValues,
_bufferSize);
_bufferSize,
_expectSize);
Assert.Fail();
}
catch (SshException ex)
@@ -22,6 +22,7 @@ namespace Renci.SshNet.Tests.Classes
private uint _height;
private IDictionary<TerminalModes, uint> _terminalModeValues;
private int _bufferSize;
private int _expectSize;
private SshException _actualException;
private void SetupData()
@@ -35,6 +36,7 @@ namespace Renci.SshNet.Tests.Classes
_height = (uint) random.Next();
_terminalModeValues = new Dictionary<TerminalModes, uint>();
_bufferSize = random.Next();
_expectSize = _bufferSize;
_actualException = null;
}
@@ -97,7 +99,8 @@ namespace Renci.SshNet.Tests.Classes
_width,
_height,
_terminalModeValues,
_bufferSize);
_bufferSize,
_expectSize);
Assert.Fail();
}
catch (SshException ex)
@@ -22,6 +22,7 @@ namespace Renci.SshNet.Tests.Classes
private uint _height;
private IDictionary<TerminalModes, uint> _terminalModeValues;
private int _bufferSize;
private int _expectSize;
private SshException _sendShellRequestException;
private SshException _actualException;
@@ -36,6 +37,7 @@ namespace Renci.SshNet.Tests.Classes
_height = (uint) random.Next();
_terminalModeValues = new Dictionary<TerminalModes, uint>();
_bufferSize = random.Next();
_expectSize = _bufferSize;
_sendShellRequestException = new SshException();
_actualException = null;
}
@@ -99,7 +101,8 @@ namespace Renci.SshNet.Tests.Classes
_width,
_height,
_terminalModeValues,
_bufferSize);
_bufferSize,
_expectSize);
Assert.Fail();
}
catch (SshException ex)
@@ -22,6 +22,7 @@ namespace Renci.SshNet.Tests.Classes
private uint _height;
private IDictionary<TerminalModes, uint> _terminalModeValues;
private int _bufferSize;
private int _expectSize;
private ShellStream _shellStream;
private void SetupData()
@@ -35,6 +36,7 @@ namespace Renci.SshNet.Tests.Classes
_height = (uint) random.Next();
_terminalModeValues = new Dictionary<TerminalModes, uint>();
_bufferSize = random.Next();
_expectSize = _bufferSize;
}
private void CreateMocks()
@@ -97,7 +99,8 @@ namespace Renci.SshNet.Tests.Classes
_width,
_height,
_terminalModeValues,
_bufferSize);
_bufferSize,
_expectSize);
}
[TestMethod]
@@ -27,6 +27,7 @@ namespace Renci.SshNet.Tests.Classes
private uint _heightPixels;
private Dictionary<TerminalModes, uint> _terminalModes;
private int _bufferSize;
private int _expectSize;
private Mock<IChannelSession> _channelSessionMock;
protected override void OnInit()
@@ -41,6 +42,7 @@ namespace Renci.SshNet.Tests.Classes
_heightPixels = (uint)random.Next();
_terminalModes = new Dictionary<TerminalModes, uint>();
_bufferSize = random.Next(100, 500);
_expectSize = random.Next(100, _bufferSize);
_encoding = Encoding.UTF8;
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
@@ -120,7 +122,8 @@ namespace Renci.SshNet.Tests.Classes
_widthPixels,
_heightPixels,
_terminalModes,
_bufferSize);
_bufferSize,
_expectSize);
}
}
}
@@ -42,7 +42,8 @@ namespace Renci.SshNet.Tests.Classes
width: 800,
height: 600,
terminalModeValues: null,
bufferSize: 1024);
bufferSize: 1024,
expectSize: 2048);
}
[TestMethod]
@@ -227,6 +228,22 @@ namespace Renci.SshNet.Tests.Classes
Assert.AreEqual("んにちは, Bonjour", _shellStream.Read());
}
[TestMethod]
public void Expect_String_LargeExpect()
{
_channelSessionStub.Receive(Encoding.UTF8.GetBytes(new string('a', 100)));
for (var i = 0; i < 10; i++)
{
_channelSessionStub.Receive(Encoding.UTF8.GetBytes(new string('b', 100)));
}
_channelSessionStub.Receive(Encoding.UTF8.GetBytes("Hello, こんにちは, Bonjour"));
_channelSessionStub.Receive(Encoding.UTF8.GetBytes(new string('c', 100)));
Assert.AreEqual($"{new string('a', 100)}{new string('b', 1000)}Hello, こんにちは, Bonjour", _shellStream.Expect($"{new string('b', 1000)}Hello, こんにちは, Bonjour"));
Assert.AreEqual($"{new string('c', 100)}", _shellStream.Read());
}
[TestMethod]
public void Expect_Timeout()
{
@@ -23,6 +23,7 @@ namespace Renci.SshNet.Tests.Classes
private Dictionary<TerminalModes, uint> _terminalModes;
private ShellStream _shellStream;
private int _bufferSize;
private int _expectSize;
private byte[] _data;
private int _offset;
@@ -47,6 +48,7 @@ namespace Renci.SshNet.Tests.Classes
_heightPixels = (uint) random.Next();
_terminalModes = new Dictionary<TerminalModes, uint>();
_bufferSize = random.Next(100, 1000);
_expectSize = random.Next(100, _bufferSize);
_data = CryptoAbstraction.GenerateRandom(_bufferSize - 10);
_offset = random.Next(1, 5);
@@ -101,7 +103,8 @@ namespace Renci.SshNet.Tests.Classes
_widthPixels,
_heightPixels,
_terminalModes,
_bufferSize);
_bufferSize,
_expectSize);
}
private void Act()
@@ -24,6 +24,7 @@ namespace Renci.SshNet.Tests.Classes
private Dictionary<TerminalModes, uint> _terminalModes;
private ShellStream _shellStream;
private int _bufferSize;
private int _expectSize;
private byte[] _data;
private int _offset;
@@ -50,6 +51,7 @@ namespace Renci.SshNet.Tests.Classes
_heightPixels = (uint)random.Next();
_terminalModes = new Dictionary<TerminalModes, uint>();
_bufferSize = random.Next(100, 1000);
_expectSize = random.Next(100, _bufferSize);
_data = CryptoAbstraction.GenerateRandom((_bufferSize * 2) + 10);
_offset = 0;
@@ -111,7 +113,8 @@ namespace Renci.SshNet.Tests.Classes
_widthPixels,
_heightPixels,
_terminalModes,
_bufferSize);
_bufferSize,
_expectSize);
}
private void Act()
@@ -23,6 +23,7 @@ namespace Renci.SshNet.Tests.Classes
private Dictionary<TerminalModes, uint> _terminalModes;
private ShellStream _shellStream;
private int _bufferSize;
private int _expectSize;
private byte[] _data;
private int _offset;
@@ -47,6 +48,7 @@ namespace Renci.SshNet.Tests.Classes
_heightPixels = (uint)random.Next();
_terminalModes = new Dictionary<TerminalModes, uint>();
_bufferSize = random.Next(100, 1000);
_expectSize = random.Next(100, _bufferSize);
_data = CryptoAbstraction.GenerateRandom(_bufferSize);
_offset = 0;
@@ -101,7 +103,8 @@ namespace Renci.SshNet.Tests.Classes
_widthPixels,
_heightPixels,
_terminalModes,
_bufferSize);
_bufferSize,
_expectSize);
}
private void Act()
@@ -25,6 +25,7 @@ namespace Renci.SshNet.Tests.Classes
private Dictionary<TerminalModes, uint> _terminalModes;
private ShellStream _shellStream;
private int _bufferSize;
private int _expectSize;
private byte[] _data;
private int _offset;
@@ -49,6 +50,7 @@ namespace Renci.SshNet.Tests.Classes
_heightPixels = (uint)random.Next();
_terminalModes = new Dictionary<TerminalModes, uint>();
_bufferSize = random.Next(100, 1000);
_expectSize = random.Next(100, _bufferSize);
_data = new byte[0];
_offset = 0;
@@ -103,7 +105,8 @@ namespace Renci.SshNet.Tests.Classes
_widthPixels,
_heightPixels,
_terminalModes,
_bufferSize);
_bufferSize,
_expectSize);
}
private void Act()
@@ -23,6 +23,7 @@ namespace Renci.SshNet.Tests.Classes
private Dictionary<TerminalModes, uint> _terminalModes;
private ShellStream _shellStream;
private int _bufferSize;
private int _expectSize;
private byte[] _data;
private int _offset;
@@ -48,6 +49,7 @@ namespace Renci.SshNet.Tests.Classes
_heightPixels = (uint)random.Next();
_terminalModes = new Dictionary<TerminalModes, uint>();
_bufferSize = random.Next(100, 1000);
_expectSize = random.Next(100, _bufferSize);
_bufferData = CryptoAbstraction.GenerateRandom(_bufferSize);
_data = CryptoAbstraction.GenerateRandom(_bufferSize - 10);
@@ -105,7 +107,8 @@ namespace Renci.SshNet.Tests.Classes
_widthPixels,
_heightPixels,
_terminalModes,
_bufferSize);
_bufferSize,
_expectSize);
_shellStream.Write(_bufferData, 0, _bufferData.Length);
}
@@ -23,6 +23,7 @@ namespace Renci.SshNet.Tests.Classes
private Dictionary<TerminalModes, uint> _terminalModes;
private ShellStream _shellStream;
private int _bufferSize;
private int _expectSize;
private byte[] _data;
private int _offset;
@@ -48,6 +49,7 @@ namespace Renci.SshNet.Tests.Classes
_heightPixels = (uint) random.Next();
_terminalModes = new Dictionary<TerminalModes, uint>();
_bufferSize = random.Next(100, 1000);
_expectSize = random.Next(100, _bufferSize);
_bufferData = CryptoAbstraction.GenerateRandom(_bufferSize);
_data = new byte[0];
@@ -103,7 +105,8 @@ namespace Renci.SshNet.Tests.Classes
_widthPixels,
_heightPixels,
_terminalModes,
_bufferSize);
_bufferSize,
_expectSize);
_shellStream.Write(_bufferData, 0, _bufferData.Length);
}
@@ -23,6 +23,7 @@ namespace Renci.SshNet.Tests.Classes
private Dictionary<TerminalModes, uint> _terminalModes;
private ShellStream _shellStream;
private int _bufferSize;
private int _expectSize;
private byte[] _data;
private int _offset;
@@ -48,6 +49,7 @@ namespace Renci.SshNet.Tests.Classes
_heightPixels = (uint) random.Next();
_terminalModes = new Dictionary<TerminalModes, uint>();
_bufferSize = random.Next(100, 1000);
_expectSize = random.Next(100, _bufferSize);
_bufferData = CryptoAbstraction.GenerateRandom(_bufferSize - 60);
_data = CryptoAbstraction.GenerateRandom(_bufferSize + 100);
@@ -103,7 +105,8 @@ namespace Renci.SshNet.Tests.Classes
_widthPixels,
_heightPixels,
_terminalModes,
_bufferSize);
_bufferSize,
_expectSize);
_shellStream.Write(_bufferData, 0, _bufferData.Length);
}
@@ -24,6 +24,7 @@ namespace Renci.SshNet.Tests.Classes
private Dictionary<TerminalModes, uint> _terminalModes;
private ShellStream _shellStream;
private int _bufferSize;
private int _expectSize;
private byte[] _data;
private int _offset;
@@ -50,6 +51,7 @@ namespace Renci.SshNet.Tests.Classes
_heightPixels = (uint) random.Next();
_terminalModes = new Dictionary<TerminalModes, uint>();
_bufferSize = random.Next(100, 1000);
_expectSize = random.Next(100, _bufferSize);
_bufferData = CryptoAbstraction.GenerateRandom(_bufferSize - 60);
_data = CryptoAbstraction.GenerateRandom(_bufferSize - _bufferData.Length + random.Next(1, 10));
@@ -111,7 +113,8 @@ namespace Renci.SshNet.Tests.Classes
_widthPixels,
_heightPixels,
_terminalModes,
_bufferSize);
_bufferSize,
_expectSize);
_shellStream.Write(_bufferData, 0, _bufferData.Length);
}
@@ -23,6 +23,7 @@ namespace Renci.SshNet.Tests.Classes
private Dictionary<TerminalModes, uint> _terminalModes;
private ShellStream _shellStream;
private int _bufferSize;
private int _expectSize;
private byte[] _data;
private int _offset;
@@ -48,6 +49,7 @@ namespace Renci.SshNet.Tests.Classes
_heightPixels = (uint)random.Next();
_terminalModes = new Dictionary<TerminalModes, uint>();
_bufferSize = random.Next(100, 1000);
_expectSize = random.Next(100, _bufferSize);
_bufferData = CryptoAbstraction.GenerateRandom(_bufferSize - 60);
_data = new byte[0];
@@ -103,7 +105,8 @@ namespace Renci.SshNet.Tests.Classes
_widthPixels,
_heightPixels,
_terminalModes,
_bufferSize);
_bufferSize,
_expectSize);
_shellStream.Write(_bufferData, 0, _bufferData.Length);
}
@@ -19,6 +19,7 @@ namespace Renci.SshNet.Tests.Classes
private uint _heightPixels;
private Dictionary<TerminalModes, uint> _terminalModes;
private int _bufferSize;
private int _expectSize;
private ShellStream _expected;
private ShellStream _actual;
@@ -35,6 +36,7 @@ namespace Renci.SshNet.Tests.Classes
_heightPixels = (uint) random.Next();
_terminalModes = new Dictionary<TerminalModes, uint>();
_bufferSize = random.Next(100, 1000);
_expectSize = random.Next(100, _bufferSize);
_expected = CreateShellStream();
}
@@ -59,7 +61,8 @@ namespace Renci.SshNet.Tests.Classes
_widthPixels,
_heightPixels,
_terminalModes,
_bufferSize))
_bufferSize,
_expectSize))
.Returns(_expected);
}
@@ -79,6 +82,7 @@ namespace Renci.SshNet.Tests.Classes
_widthPixels,
_heightPixels,
_bufferSize,
_expectSize,
_terminalModes);
}
@@ -92,7 +96,8 @@ namespace Renci.SshNet.Tests.Classes
_widthPixels,
_heightPixels,
_terminalModes,
_bufferSize),
_bufferSize,
_expectSize),
Times.Once);
}
@@ -130,6 +135,7 @@ namespace Renci.SshNet.Tests.Classes
_widthPixels,
_heightPixels,
_terminalModes,
1,
1);
}
}
@@ -19,6 +19,7 @@ namespace Renci.SshNet.Tests.Classes
private uint _widthPixels;
private uint _heightPixels;
private int _bufferSize;
private int _expectSize;
private ShellStream _expected;
private ShellStream _actual;
@@ -34,6 +35,7 @@ namespace Renci.SshNet.Tests.Classes
_widthPixels = (uint)random.Next();
_heightPixels = (uint)random.Next();
_bufferSize = random.Next(100, 1000);
_expectSize = random.Next(100, _bufferSize);
_expected = CreateShellStream();
}
@@ -58,7 +60,8 @@ namespace Renci.SshNet.Tests.Classes
_widthPixels,
_heightPixels,
null,
_bufferSize))
_bufferSize,
_expectSize))
.Returns(_expected);
}
@@ -77,7 +80,8 @@ namespace Renci.SshNet.Tests.Classes
_heightRows,
_widthPixels,
_heightPixels,
_bufferSize);
_bufferSize,
_expectSize);
}
[TestMethod]
@@ -90,7 +94,8 @@ namespace Renci.SshNet.Tests.Classes
_widthPixels,
_heightPixels,
null,
_bufferSize),
_bufferSize,
_expectSize),
Times.Once);
}
@@ -128,6 +133,7 @@ namespace Renci.SshNet.Tests.Classes
_widthPixels,
_heightPixels,
null,
1,
1);
}
}