mirror of
https://github.com/sshnet/SSH.NET.git
synced 2026-09-10 17:25:51 +00:00
6039e121a8
Where beneficial, add additional overrides from the base Stream class. Namely the Span variants and for PipeStream, the WriteAsync variants (see comments). The change also adds an internal type borrowed from the runtime repo for easier buffer management, which could also be used elsewhere.
298 lines
9.1 KiB
C#
298 lines
9.1 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Threading.Tasks;
|
|
|
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
|
|
#if NETFRAMEWORK
|
|
using Renci.SshNet.Abstractions;
|
|
#endif
|
|
using Renci.SshNet.Common;
|
|
using Renci.SshNet.Tests.Common;
|
|
|
|
namespace Renci.SshNet.Tests.Classes.Common
|
|
{
|
|
[TestClass]
|
|
public class PipeStreamTest : TestBase
|
|
{
|
|
[TestMethod]
|
|
public void Test_PipeStream_Write_Read_Buffer()
|
|
{
|
|
var testBuffer = new byte[1024];
|
|
new Random().NextBytes(testBuffer);
|
|
|
|
var outputBuffer = new byte[1024];
|
|
|
|
using (var stream = new PipeStream())
|
|
{
|
|
stream.Write(testBuffer, 0, 512);
|
|
|
|
Assert.AreEqual(512, stream.Length);
|
|
|
|
Assert.AreEqual(128, stream.Read(outputBuffer, 64, 128));
|
|
|
|
Assert.AreEqual(384, stream.Length);
|
|
|
|
CollectionAssert.AreEqual(new byte[64].Concat(testBuffer.Take(128)).Concat(new byte[832]), outputBuffer);
|
|
}
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Test_PipeStream_Write_Read_Byte()
|
|
{
|
|
var testBuffer = new byte[1024];
|
|
new Random().NextBytes(testBuffer);
|
|
|
|
using (var stream = new PipeStream())
|
|
{
|
|
stream.Write(testBuffer, 0, testBuffer.Length);
|
|
Assert.AreEqual(1024, stream.Length);
|
|
Assert.AreEqual(testBuffer[0], stream.ReadByte());
|
|
Assert.AreEqual(1023, stream.Length);
|
|
Assert.AreEqual(testBuffer[1], stream.ReadByte());
|
|
Assert.AreEqual(1022, stream.Length);
|
|
}
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Read()
|
|
{
|
|
var target = new PipeStream();
|
|
target.WriteByte(0x0a);
|
|
target.WriteByte(0x0d);
|
|
target.WriteByte(0x09);
|
|
|
|
var readBuffer = new byte[2];
|
|
var bytesRead = target.Read(readBuffer, 0, readBuffer.Length);
|
|
Assert.AreEqual(2, bytesRead);
|
|
Assert.AreEqual(0x0a, readBuffer[0]);
|
|
Assert.AreEqual(0x0d, readBuffer[1]);
|
|
|
|
var writeBuffer = new byte[] { 0x05, 0x03 };
|
|
target.Write(writeBuffer, 0, writeBuffer.Length);
|
|
|
|
readBuffer = new byte[4];
|
|
bytesRead = target.Read(readBuffer, 0, readBuffer.Length);
|
|
Assert.AreEqual(3, bytesRead);
|
|
Assert.AreEqual(0x09, readBuffer[0]);
|
|
Assert.AreEqual(0x05, readBuffer[1]);
|
|
Assert.AreEqual(0x03, readBuffer[2]);
|
|
Assert.AreEqual(0x00, readBuffer[3]);
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task Read_NonEmptyArray_OnlyReturnsZeroAfterDispose()
|
|
{
|
|
// When there is no data available, a read should block,
|
|
// but then unblock (and return 0) after disposal.
|
|
|
|
var pipeStream = new PipeStream();
|
|
|
|
Task<int> readTask = pipeStream.ReadAsync(new byte[16], 0, 16);
|
|
|
|
await Task.Delay(50);
|
|
|
|
Assert.IsFalse(readTask.IsCompleted);
|
|
|
|
await pipeStream.DisposeAsync();
|
|
|
|
Assert.AreEqual(0, await readTask);
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task Read_EmptyArray_OnlyReturnsZeroAfterDispose()
|
|
{
|
|
// Similarly, zero byte reads should still block until after disposal.
|
|
|
|
var pipeStream = new PipeStream();
|
|
|
|
Task<int> readTask = pipeStream.ReadAsync(Array.Empty<byte>(), 0, 0);
|
|
|
|
await Task.Delay(50);
|
|
|
|
Assert.IsFalse(readTask.IsCompleted);
|
|
|
|
await pipeStream.DisposeAsync();
|
|
|
|
Assert.AreEqual(0, await readTask);
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task Read_EmptyArray_OnlyReturnsZeroWhenDataAvailable()
|
|
{
|
|
// And zero byte reads should block but then return 0 once data
|
|
// is available.
|
|
|
|
var pipeStream = new PipeStream();
|
|
|
|
Task<int> readTask = pipeStream.ReadAsync(Array.Empty<byte>(), 0, 0);
|
|
|
|
await Task.Delay(50);
|
|
|
|
Assert.IsFalse(readTask.IsCompleted);
|
|
|
|
await pipeStream.WriteAsync(new byte[] { 1, 2, 3, 4 }, 0, 4);
|
|
|
|
Assert.AreEqual(0, await readTask);
|
|
}
|
|
|
|
#if NET
|
|
[TestMethod]
|
|
public async Task Read_EmptySpan_OnlyReturnsZeroWhenDataAvailable()
|
|
{
|
|
// And zero byte reads should block but then return 0 once data
|
|
// is available (the span version).
|
|
|
|
var pipeStream = new PipeStream();
|
|
|
|
ValueTask<int> readTask = pipeStream.ReadAsync(Memory<byte>.Empty);
|
|
|
|
await Task.Delay(50);
|
|
|
|
Assert.IsFalse(readTask.IsCompleted);
|
|
|
|
await pipeStream.WriteAsync(new byte[] { 1, 2, 3, 4 });
|
|
|
|
Assert.AreEqual(0, await readTask);
|
|
}
|
|
#endif
|
|
|
|
[TestMethod]
|
|
public void Read_AfterDispose_StillWorks()
|
|
{
|
|
var pipeStream = new PipeStream();
|
|
|
|
pipeStream.Write(new byte[] { 1, 2, 3, 4 }, 0, 4);
|
|
|
|
pipeStream.Dispose();
|
|
#pragma warning disable S3966 // Objects should not be disposed more than once
|
|
pipeStream.Dispose(); // Check that multiple Dispose is OK.
|
|
#pragma warning restore S3966 // Objects should not be disposed more than once
|
|
|
|
Assert.IsTrue(pipeStream.CanRead);
|
|
|
|
Assert.AreEqual(4, pipeStream.Read(new byte[5], 0, 5));
|
|
Assert.AreEqual(0, pipeStream.Read(new byte[5], 0, 5));
|
|
}
|
|
|
|
[TestMethod]
|
|
public void SeekShouldThrowNotSupportedException()
|
|
{
|
|
var target = new PipeStream();
|
|
Assert.Throws<NotSupportedException>(() => target.Seek(offset: 0, SeekOrigin.Begin));
|
|
}
|
|
|
|
[TestMethod]
|
|
public void SetLengthShouldThrowNotSupportedException()
|
|
{
|
|
var target = new PipeStream();
|
|
Assert.Throws<NotSupportedException>(() => target.SetLength(1));
|
|
}
|
|
|
|
[TestMethod]
|
|
public void WriteTest()
|
|
{
|
|
var target = new PipeStream();
|
|
|
|
var writeBuffer = new byte[] { 0x0a, 0x05, 0x0d };
|
|
target.Write(writeBuffer, 0, 2);
|
|
|
|
writeBuffer = new byte[] { 0x02, 0x04, 0x03, 0x06, 0x09 };
|
|
target.Write(writeBuffer, 1, 2);
|
|
|
|
var readBuffer = new byte[6];
|
|
var bytesRead = target.Read(readBuffer, 0, 4);
|
|
|
|
Assert.AreEqual(4, bytesRead);
|
|
Assert.AreEqual(0x0a, readBuffer[0]);
|
|
Assert.AreEqual(0x05, readBuffer[1]);
|
|
Assert.AreEqual(0x04, readBuffer[2]);
|
|
Assert.AreEqual(0x03, readBuffer[3]);
|
|
Assert.AreEqual(0x00, readBuffer[4]);
|
|
Assert.AreEqual(0x00, readBuffer[5]);
|
|
}
|
|
|
|
#if NET
|
|
[TestMethod]
|
|
public void WriteTest_Span()
|
|
{
|
|
var target = new PipeStream();
|
|
|
|
var writeBuffer = new byte[] { 0x0a, 0x05, 0x0d };
|
|
target.Write(writeBuffer.AsSpan(0, 2));
|
|
|
|
writeBuffer = new byte[] { 0x02, 0x04, 0x03, 0x06, 0x09 };
|
|
target.Write(writeBuffer.AsSpan(1, 2));
|
|
|
|
var readBuffer = new byte[6];
|
|
var bytesRead = target.Read(readBuffer.AsSpan(0, 4));
|
|
|
|
Assert.AreEqual(4, bytesRead);
|
|
Assert.AreEqual(0x0a, readBuffer[0]);
|
|
Assert.AreEqual(0x05, readBuffer[1]);
|
|
Assert.AreEqual(0x04, readBuffer[2]);
|
|
Assert.AreEqual(0x03, readBuffer[3]);
|
|
Assert.AreEqual(0x00, readBuffer[4]);
|
|
Assert.AreEqual(0x00, readBuffer[5]);
|
|
}
|
|
#endif
|
|
|
|
[TestMethod]
|
|
public void CanReadTest()
|
|
{
|
|
var target = new PipeStream();
|
|
Assert.IsTrue(target.CanRead);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void CanSeekTest()
|
|
{
|
|
var target = new PipeStream();
|
|
Assert.IsFalse(target.CanSeek);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void CanWriteTest()
|
|
{
|
|
var target = new PipeStream();
|
|
Assert.IsTrue(target.CanWrite);
|
|
target.Dispose();
|
|
Assert.IsFalse(target.CanWrite);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void LengthTest()
|
|
{
|
|
var target = new PipeStream();
|
|
Assert.AreEqual(0L, target.Length);
|
|
target.Write(new byte[] { 0x0a, 0x05, 0x0d }, 0, 2);
|
|
Assert.AreEqual(2L, target.Length);
|
|
target.WriteByte(0x0a);
|
|
Assert.AreEqual(3L, target.Length);
|
|
_ = target.Read(new byte[2], 0, 2);
|
|
Assert.AreEqual(1L, target.Length);
|
|
_ = target.ReadByte();
|
|
Assert.AreEqual(0L, target.Length);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Position_GetterAlwaysReturnsZero()
|
|
{
|
|
var target = new PipeStream();
|
|
|
|
Assert.AreEqual(0, target.Position);
|
|
target.WriteByte(0x0a);
|
|
Assert.AreEqual(0, target.Position);
|
|
_ = target.ReadByte();
|
|
Assert.AreEqual(0, target.Position);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Position_SetterAlwaysThrowsNotSupportedException()
|
|
{
|
|
var target = new PipeStream();
|
|
Assert.Throws<NotSupportedException>(() => target.Position = 0);
|
|
}
|
|
}
|
|
}
|