diff --git a/appveyor.yml b/appveyor.yml index c5bb4a18e..2425ef712 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -9,6 +9,6 @@ build: test_script: - cmd: >- - vstest.console /logger:Appveyor src\Renci.SshNet.Tests\bin\Debug\net40\Renci.SshNet.Tests.dll /TestCaseFilter:"TestCategory!=integration&TestCategory!=LongRunning" + vstest.console /logger:Appveyor src\Renci.SshNet.Tests\bin\Debug\net35\Renci.SshNet.Tests.dll /TestCaseFilter:"TestCategory!=integration&TestCategory!=LongRunning" - vstest.console /logger:Appveyor src\Renci.SshNet.Tests\bin\Debug\net35\Renci.SshNet.Tests.dll /TestCaseFilter:"TestCategory!=integration&TestCategory!=LongRunning" \ No newline at end of file + vstest.console /logger:Appveyor src\Renci.SshNet.Tests\bin\Debug\net472\Renci.SshNet.Tests.dll /TestCaseFilter:"TestCategory!=integration&TestCategory!=LongRunning" diff --git a/src/Renci.SshNet.Tests/Classes/BaseClientTest_Connected_KeepAliveInterval_NegativeOne.cs b/src/Renci.SshNet.Tests/Classes/BaseClientTest_Connected_KeepAliveInterval_NegativeOne.cs index e3b10c876..46d730119 100644 --- a/src/Renci.SshNet.Tests/Classes/BaseClientTest_Connected_KeepAliveInterval_NegativeOne.cs +++ b/src/Renci.SshNet.Tests/Classes/BaseClientTest_Connected_KeepAliveInterval_NegativeOne.cs @@ -94,7 +94,7 @@ public void IsConnectedOnSessionShouldBeInvokedOnce() } [TestMethod] - public void SendMessageOnSessionShouldBeInvokedThreeTimes() + public void SendMessageOnSessionShouldBeInvokedOneTime() { // allow keep-alive to be sent once Thread.Sleep(100); diff --git a/src/Renci.SshNet.Tests/Classes/Common/PacketDumpTest.cs b/src/Renci.SshNet.Tests/Classes/Common/PacketDumpTest.cs index 004019157..3b481bf46 100644 --- a/src/Renci.SshNet.Tests/Classes/Common/PacketDumpTest.cs +++ b/src/Renci.SshNet.Tests/Classes/Common/PacketDumpTest.cs @@ -37,7 +37,11 @@ public void Create_ByteArrayAndIndentLevel_IndentLevelLessThanZero() catch (ArgumentOutOfRangeException ex) { Assert.IsNull(ex.InnerException); +#if NETFRAMEWORK Assert.AreEqual(string.Format("Cannot be less than zero.{0}Parameter name: {1}", Environment.NewLine, ex.ParamName), ex.Message); +#else + Assert.AreEqual(string.Format("Cannot be less than zero. (Parameter '{1}')", Environment.NewLine, ex.ParamName), ex.Message); +#endif Assert.AreEqual("indentLevel", ex.ParamName); } } diff --git a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndDirectoryInfo_SendExecRequestReturnsFalse.cs b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndDirectoryInfo_SendExecRequestReturnsFalse.cs index 9c5ed4853..dd7e61e61 100644 --- a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndDirectoryInfo_SendExecRequestReturnsFalse.cs +++ b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndDirectoryInfo_SendExecRequestReturnsFalse.cs @@ -54,11 +54,11 @@ protected override void SetupMocks() .Setup(p => p.SendExecRequest(string.Format("scp -prf {0}", _transformedPath))) .Returns(false); _channelSessionMock.InSequence(sequence).Setup(p => p.Dispose()); +#if NET35 _pipeStreamMock.As().InSequence(sequence).Setup(p => p.Dispose()); - - // On .NET Core, Dispose() in turn invokes Close() and since we're not mocking - // an interface, we need to expect this call as well - _pipeStreamMock.Setup(p => p.Close()); +#else + _pipeStreamMock.InSequence(sequence).Setup(p => p.Close()); +#endif } protected override void Arrange() @@ -106,7 +106,11 @@ public void DisposeOnChannelShouldBeInvokedOnce() [TestMethod] public void DisposeOnPipeStreamShouldBeInvokedOnce() { +#if NET35 _pipeStreamMock.As().Verify(p => p.Dispose(), Times.Once); +#else + _pipeStreamMock.Verify(p => p.Close(), Times.Once); +#endif } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndFileInfo_SendExecRequestReturnsFalse.cs b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndFileInfo_SendExecRequestReturnsFalse.cs index 8ba4525bc..8d1d1a1a2 100644 --- a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndFileInfo_SendExecRequestReturnsFalse.cs +++ b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndFileInfo_SendExecRequestReturnsFalse.cs @@ -53,11 +53,11 @@ protected override void SetupMocks() _channelSessionMock.InSequence(sequence) .Setup(p => p.SendExecRequest(string.Format("scp -pf {0}", _transformedPath))).Returns(false); _channelSessionMock.InSequence(sequence).Setup(p => p.Dispose()); +#if NET35 _pipeStreamMock.As().InSequence(sequence).Setup(p => p.Dispose()); - - // On .NET Core, Dispose() in turn invokes Close() and since we're not mocking - // an interface, we need to expect this call as well - _pipeStreamMock.Setup(p => p.Close()); +#else + _pipeStreamMock.InSequence(sequence).Setup(p => p.Close()); +#endif } protected override void Arrange() @@ -105,7 +105,11 @@ public void DisposeOnChannelShouldBeInvokedOnce() [TestMethod] public void DisposeOnPipeStreamShouldBeInvokedOnce() { +#if NET35 _pipeStreamMock.As().Verify(p => p.Dispose(), Times.Once); +#else + _pipeStreamMock.Verify(p => p.Close(), Times.Once); +#endif } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndStream_SendExecRequestReturnsFalse.cs b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndStream_SendExecRequestReturnsFalse.cs index c1504aec1..0fe2566fa 100644 --- a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndStream_SendExecRequestReturnsFalse.cs +++ b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndStream_SendExecRequestReturnsFalse.cs @@ -54,11 +54,11 @@ protected override void SetupMocks() .Setup(p => p.SendExecRequest(string.Format("scp -f {0}", _transformedPath))) .Returns(false); _channelSessionMock.InSequence(sequence).Setup(p => p.Dispose()); +#if NET35 _pipeStreamMock.As().InSequence(sequence).Setup(p => p.Dispose()); - - // On .NET Core, Dispose() in turn invokes Close() and since we're not mocking - // an interface, we need to expect this call as well - _pipeStreamMock.Setup(p => p.Close()); +#else + _pipeStreamMock.InSequence(sequence).Setup(p => p.Close()); +#endif } protected override void Arrange() @@ -116,7 +116,11 @@ public void DisposeOnChannelShouldBeInvokedOnce() [TestMethod] public void DisposeOnPipeStreamShouldBeInvokedOnce() { +#if NET35 _pipeStreamMock.As().Verify(p => p.Dispose(), Times.Once); +#else + _pipeStreamMock.Verify(p => p.Close(), Times.Once); +#endif } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_DirectoryInfoAndPath_SendExecRequestReturnsFalse.cs b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_DirectoryInfoAndPath_SendExecRequestReturnsFalse.cs index 6791e296f..5c8d7c282 100644 --- a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_DirectoryInfoAndPath_SendExecRequestReturnsFalse.cs +++ b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_DirectoryInfoAndPath_SendExecRequestReturnsFalse.cs @@ -53,11 +53,11 @@ protected override void SetupMocks() .Setup(p => p.SendExecRequest(string.Format("scp -r -p -d -t {0}", _transformedPath))) .Returns(false); _channelSessionMock.InSequence(sequence).Setup(p => p.Dispose()); +#if NET35 _pipeStreamMock.As().InSequence(sequence).Setup(p => p.Dispose()); - - // On .NET Core, Dispose() in turn invokes Close() and since we're not mocking - // an interface, we need to expect this call as well - _pipeStreamMock.Setup(p => p.Close()); +#else + _pipeStreamMock.InSequence(sequence).Setup(p => p.Close()); +#endif } protected override void Arrange() @@ -105,7 +105,11 @@ public void DisposeOnChannelShouldBeInvokedOnce() [TestMethod] public void DisposeOnPipeStreamShouldBeInvokedOnce() { +#if NET35 _pipeStreamMock.As().Verify(p => p.Dispose(), Times.Once); +#else + _pipeStreamMock.Verify(p => p.Close(), Times.Once); +#endif } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_FileInfoAndPath_SendExecRequestReturnsFalse.cs b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_FileInfoAndPath_SendExecRequestReturnsFalse.cs index 9a065ee21..57d89d698 100644 --- a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_FileInfoAndPath_SendExecRequestReturnsFalse.cs +++ b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_FileInfoAndPath_SendExecRequestReturnsFalse.cs @@ -59,12 +59,12 @@ protected override void SetupMocks() .Setup(p => p.SendExecRequest(string.Format("scp -t -d {0}", _transformedPath))) .Returns(false); _channelSessionMock.InSequence(sequence).Setup(p => p.Dispose()); +#if NET35 _pipeStreamMock.As().InSequence(sequence).Setup(p => p.Dispose()); - - // On .NET Core, Dispose() in turn invokes Close() and since we're not mocking - // an interface, we need to expect this call as well - _pipeStreamMock.Setup(p => p.Close()); -} +#else + _pipeStreamMock.InSequence(sequence).Setup(p => p.Close()); +#endif + } protected override void Arrange() { @@ -122,7 +122,11 @@ public void DisposeOnChannelShouldBeInvokedOnce() [TestMethod] public void DisposeOnPipeStreamShouldBeInvokedOnce() { +#if NET35 _pipeStreamMock.As().Verify(p => p.Dispose(), Times.Once); +#else + _pipeStreamMock.Verify(p => p.Close(), Times.Once); +#endif } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_FileInfoAndPath_Success.cs b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_FileInfoAndPath_Success.cs index d86191e5a..3cae19e67 100644 --- a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_FileInfoAndPath_Success.cs +++ b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_FileInfoAndPath_Success.cs @@ -84,11 +84,11 @@ protected override void SetupMocks() p => p.SendData(It.Is(b => b.SequenceEqual(new byte[] {0})))); _pipeStreamMock.InSequence(sequence).Setup(p => p.ReadByte()).Returns(0); _channelSessionMock.InSequence(sequence).Setup(p => p.Dispose()); +#if NET35 _pipeStreamMock.As().InSequence(sequence).Setup(p => p.Dispose()); - - // On .NET Core, Dispose() in turn invokes Close() and since we're not mocking - // an interface, we need to expect this call as well - _pipeStreamMock.Setup(p => p.Close()); +#else + _pipeStreamMock.InSequence(sequence).Setup(p => p.Close()); +#endif } protected override void Arrange() @@ -134,7 +134,11 @@ public void DisposeOnChannelShouldBeInvokedOnce() [TestMethod] public void DisposeOnPipeStreamShouldBeInvokedOnce() { +#if NET35 _pipeStreamMock.As().Verify(p => p.Dispose(), Times.Once); +#else + _pipeStreamMock.Verify(p => p.Close(), Times.Once); +#endif } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_StreamAndPath_SendExecRequestReturnsFalse.cs b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_StreamAndPath_SendExecRequestReturnsFalse.cs index 5facca290..21c761134 100644 --- a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_StreamAndPath_SendExecRequestReturnsFalse.cs +++ b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_StreamAndPath_SendExecRequestReturnsFalse.cs @@ -57,11 +57,11 @@ protected override void SetupMocks() .Setup(p => p.SendExecRequest(string.Format("scp -t -d {0}", _transformedPath))) .Returns(false); _channelSessionMock.InSequence(sequence).Setup(p => p.Dispose()); +#if NET35 _pipeStreamMock.As().InSequence(sequence).Setup(p => p.Dispose()); - - // On .NET Core, Dispose() in turn invokes Close() and since we're not mocking - // an interface, we need to expect this call as well - _pipeStreamMock.Setup(p => p.Close()); +#else + _pipeStreamMock.InSequence(sequence).Setup(p => p.Close()); +#endif } protected override void Arrange() @@ -119,7 +119,11 @@ public void DisposeOnChannelShouldBeInvokedOnce() [TestMethod] public void DisposeOnPipeStreamShouldBeInvokedOnce() { +#if NET35 _pipeStreamMock.As().Verify(p => p.Dispose(), Times.Once); +#else + _pipeStreamMock.Verify(p => p.Close(), Times.Once); +#endif } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamAsyncTestBase.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamAsyncTestBase.cs new file mode 100644 index 000000000..b8b7b4ae9 --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamAsyncTestBase.cs @@ -0,0 +1,69 @@ +#if FEATURE_TAP +using System; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Sftp; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + public abstract class SftpFileStreamAsyncTestBase + { + internal Mock SftpSessionMock; + protected MockSequence MockSequence; + + protected virtual Task ArrangeAsync() + { + SetupData(); + CreateMocks(); + SetupMocks(); + return Task.CompletedTask; + } + + protected virtual void SetupData() + { + MockSequence = new MockSequence(); + } + + protected abstract void SetupMocks(); + + private void CreateMocks() + { + SftpSessionMock = new Mock(MockBehavior.Strict); + } + + [TestInitialize] + public async Task SetUpAsync() + { + await ArrangeAsync(); + await ActAsync(); + } + + protected abstract Task ActAsync(); + + protected byte[] GenerateRandom(int length) + { + return GenerateRandom(length, new Random()); + } + + protected byte[] GenerateRandom(int length, Random random) + { + var buffer = new byte[length]; + random.NextBytes(buffer); + return buffer; + } + + protected byte[] GenerateRandom(uint length) + { + return GenerateRandom(length, new Random()); + } + + protected byte[] GenerateRandom(uint length, Random random) + { + var buffer = new byte[length]; + random.NextBytes(buffer); + return buffer; + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileAccessInvalid.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileAccessInvalid.cs new file mode 100644 index 000000000..fab12dad6 --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileAccessInvalid.cs @@ -0,0 +1,57 @@ +#if FEATURE_TAP +using System; +using System.IO; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Renci.SshNet.Sftp; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_OpenAsync_FileAccessInvalid : SftpFileStreamAsyncTestBase + { + private Random _random; + private string _path; + private FileMode _fileMode; + private FileAccess _fileAccess; + private int _bufferSize; + private ArgumentOutOfRangeException _actualException; + + protected override void SetupData() + { + base.SetupData(); + + _random = new Random(); + _path = _random.Next().ToString(); + _fileMode = FileMode.Open; + _fileAccess = 0; + _bufferSize = _random.Next(5, 1000); + } + + protected override void SetupMocks() + { + } + + protected override async Task ActAsync() + { + try + { + await SftpFileStream.OpenAsync(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize, default); + Assert.Fail(); + } + catch (ArgumentOutOfRangeException ex) + { + _actualException = ex; + } + } + + [TestMethod] + public void CtorShouldHaveThrownArgumentException() + { + Assert.IsNotNull(_actualException); + Assert.IsNull(_actualException.InnerException); + Assert.AreEqual("access", _actualException.ParamName); + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeAppend_FileAccessRead.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeAppend_FileAccessRead.cs new file mode 100644 index 000000000..0ffeaeb6c --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeAppend_FileAccessRead.cs @@ -0,0 +1,58 @@ +#if FEATURE_TAP +using System; +using System.IO; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Renci.SshNet.Sftp; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_OpenAsync_FileModeAppend_FileAccessRead : SftpFileStreamAsyncTestBase + { + private Random _random; + private string _path; + private FileMode _fileMode; + private FileAccess _fileAccess; + private int _bufferSize; + private ArgumentException _actualException; + + protected override void SetupData() + { + base.SetupData(); + + _random = new Random(); + _path = _random.Next().ToString(); + _fileMode = FileMode.Append; + _fileAccess = FileAccess.Read; + _bufferSize = _random.Next(5, 1000); + } + + protected override void SetupMocks() + { + } + + protected override async Task ActAsync() + { + try + { + await SftpFileStream.OpenAsync(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize, default); + Assert.Fail(); + } + catch (ArgumentException ex) + { + _actualException = ex; + } + } + + [TestMethod] + public void CtorShouldHaveThrownArgumentException() + { + Assert.IsNotNull(_actualException); + Assert.IsNull(_actualException.InnerException); + Assert.AreEqual(string.Format("{0} mode can be requested only when combined with write-only access.", _fileMode), _actualException.Message); + Assert.IsNull(_actualException.ParamName); + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeAppend_FileAccessReadWrite.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeAppend_FileAccessReadWrite.cs new file mode 100644 index 000000000..2ed8cd14f --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeAppend_FileAccessReadWrite.cs @@ -0,0 +1,58 @@ +#if FEATURE_TAP +using System; +using System.IO; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Renci.SshNet.Sftp; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_OpenAsync_FileModeAppend_FileAccessReadWrite : SftpFileStreamAsyncTestBase + { + private Random _random; + private string _path; + private FileMode _fileMode; + private FileAccess _fileAccess; + private int _bufferSize; + private ArgumentException _actualException; + + protected override void SetupData() + { + base.SetupData(); + + _random = new Random(); + _path = _random.Next().ToString(); + _fileMode = FileMode.Append; + _fileAccess = FileAccess.ReadWrite; + _bufferSize = _random.Next(5, 1000); + } + + protected override void SetupMocks() + { + } + + protected override async Task ActAsync() + { + try + { + await SftpFileStream.OpenAsync(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize, default); + Assert.Fail(); + } + catch (ArgumentException ex) + { + _actualException = ex; + } + } + + [TestMethod] + public void CtorShouldHaveThrownArgumentException() + { + Assert.IsNotNull(_actualException); + Assert.IsNull(_actualException.InnerException); + Assert.AreEqual(string.Format("{0} mode can be requested only when combined with write-only access.", _fileMode), _actualException.Message); + Assert.IsNull(_actualException.ParamName); + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeAppend_FileAccessWrite.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeAppend_FileAccessWrite.cs new file mode 100644 index 000000000..8d9bc960b --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeAppend_FileAccessWrite.cs @@ -0,0 +1,155 @@ +#if FEATURE_TAP +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Sftp; +using Renci.SshNet.Tests.Common; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_OpenAsync_FileModeAppend_FileAccessWrite : SftpFileStreamAsyncTestBase + { + private Random _random; + private string _path; + private FileMode _fileMode; + private FileAccess _fileAccess; + private int _bufferSize; + private uint _readBufferSize; + private uint _writeBufferSize; + private byte[] _handle; + private SftpFileStream _target; + private SftpFileAttributes _fileAttributes; + private CancellationToken _cancellationToken; + + protected override void SetupData() + { + base.SetupData(); + + _random = new Random(); + _path = _random.Next().ToString(); + _fileMode = FileMode.Append; + _fileAccess = FileAccess.Write; + _bufferSize = _random.Next(5, 1000); + _readBufferSize = (uint) _random.Next(5, 1000); + _writeBufferSize = (uint) _random.Next(5, 1000); + _handle = GenerateRandom(_random.Next(1, 10), _random); + _fileAttributes = new SftpFileAttributesBuilder().WithLastAccessTime(DateTime.UtcNow.AddSeconds(_random.Next())) + .WithLastWriteTime(DateTime.UtcNow.AddSeconds(_random.Next())) + .WithSize(_random.Next()) + .WithUserId(_random.Next()) + .WithGroupId(_random.Next()) + .WithPermissions((uint) _random.Next()) + .Build(); + _cancellationToken = new CancellationToken(); + } + + protected override void SetupMocks() + { + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestOpenAsync(_path, Flags.Write | Flags.Append | Flags.CreateNewOrOpen, _cancellationToken)) + .ReturnsAsync(_handle); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestFStatAsync(_handle, _cancellationToken)) + .ReturnsAsync(_fileAttributes); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalReadLength((uint)_bufferSize)) + .Returns(_readBufferSize); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalWriteLength((uint)_bufferSize, _handle)) + .Returns(_writeBufferSize); + } + + protected override async Task ActAsync() + { + _target = await SftpFileStream.OpenAsync(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize, _cancellationToken); + } + + + [TestMethod] + public void CanReadShouldReturnFalse() + { + Assert.IsFalse(_target.CanRead); + } + + [TestMethod] + public void CanSeekShouldReturnTrue() + { + Assert.IsTrue(_target.CanSeek); + } + + [TestMethod] + public void CanWriteShouldReturnTrue() + { + Assert.IsTrue(_target.CanWrite); + } + + [TestMethod] + public void CanTimeoutShouldReturnTrue() + { + Assert.IsTrue(_target.CanTimeout); + } + + [TestMethod] + public void PositionShouldReturnSizeOfFile() + { + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + var actual = _target.Position; + + Assert.AreEqual(_fileAttributes.Size, actual); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + } + + [TestMethod] + public async Task ReadShouldThrowNotSupportedException() + { + var buffer = new byte[_readBufferSize]; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + try + { + await _target.ReadAsync(buffer, 0, buffer.Length, _cancellationToken); + Assert.Fail(); + } + catch (NotSupportedException ex) + { + Assert.IsNull(ex.InnerException); + } + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + } + + [TestMethod] + public async Task WriteShouldStartWritingAtEndOfFile() + { + var buffer = new byte[_writeBufferSize]; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence).Setup(p => p.RequestWriteAsync(_handle, (ulong)_fileAttributes.Size, buffer, 0, buffer.Length, _cancellationToken)).Returns(Task.CompletedTask); + + await _target.WriteAsync(buffer, 0, buffer.Length, _cancellationToken); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + SftpSessionMock.Verify(p => p.RequestWriteAsync(_handle, (ulong)_fileAttributes.Size, buffer, 0, buffer.Length, _cancellationToken), Times.Once); + } + + [TestMethod] + public void RequestOpenOnSftpSessionShouldBeInvokedOnce() + { + SftpSessionMock.Verify(p => p.RequestOpenAsync(_path, Flags.Write | Flags.Append | Flags.CreateNewOrOpen, default), Times.Once); + } + + [TestMethod] + public void RequestFStatOnSftpSessionShouldBeInvokedOnce() + { + SftpSessionMock.Verify(p => p.RequestFStatAsync(_handle, default), Times.Once); + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreateNew_FileAccessRead.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreateNew_FileAccessRead.cs new file mode 100644 index 000000000..eb83af777 --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreateNew_FileAccessRead.cs @@ -0,0 +1,58 @@ +#if FEATURE_TAP +using System; +using System.IO; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Renci.SshNet.Sftp; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_OpenAsync_FileModeCreateNew_FileAccessRead : SftpFileStreamAsyncTestBase + { + private Random _random; + private string _path; + private FileMode _fileMode; + private FileAccess _fileAccess; + private int _bufferSize; + private ArgumentException _actualException; + + protected override void SetupData() + { + base.SetupData(); + + _random = new Random(); + _path = _random.Next().ToString(); + _fileMode = FileMode.CreateNew; + _fileAccess = FileAccess.Read; + _bufferSize = _random.Next(5, 1000); + } + + protected override void SetupMocks() + { + } + + protected override async Task ActAsync() + { + try + { + await SftpFileStream.OpenAsync(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize, default); + Assert.Fail(); + } + catch (ArgumentException ex) + { + _actualException = ex; + } + } + + [TestMethod] + public void CtorShouldHaveThrownArgumentException() + { + Assert.IsNotNull(_actualException); + Assert.IsNull(_actualException.InnerException); + Assert.AreEqual(string.Format("Combining {0}: {1} with {2}: {3} is invalid.", typeof(FileMode).Name, _fileMode, typeof(FileAccess).Name, _fileAccess), _actualException.Message); + Assert.IsNull(_actualException.ParamName); + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreateNew_FileAccessReadWrite.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreateNew_FileAccessReadWrite.cs new file mode 100644 index 000000000..5c2318086 --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreateNew_FileAccessReadWrite.cs @@ -0,0 +1,136 @@ +#if FEATURE_TAP +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Common; +using Renci.SshNet.Sftp; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_OpenAsync_FileModeCreateNew_FileAccessReadWrite : SftpFileStreamAsyncTestBase + { + private Random _random; + private string _path; + private FileMode _fileMode; + private FileAccess _fileAccess; + private int _bufferSize; + private uint _readBufferSize; + private uint _writeBufferSize; + private byte[] _handle; + private SftpFileStream _target; + private CancellationToken _cancellationToken; + + protected override void SetupData() + { + base.SetupData(); + + _random = new Random(); + _path = _random.Next().ToString(); + _fileMode = FileMode.CreateNew; + _fileAccess = FileAccess.ReadWrite; + _bufferSize = _random.Next(5, 1000); + _readBufferSize = (uint)_random.Next(5, 1000); + _writeBufferSize = (uint)_random.Next(5, 1000); + _handle = GenerateRandom(_random.Next(1, 10), _random); + _cancellationToken = new CancellationToken(); + } + + protected override void SetupMocks() + { + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestOpenAsync(_path, Flags.Read | Flags.Write | Flags.CreateNew, _cancellationToken)) + .ReturnsAsync(_handle); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalReadLength((uint) _bufferSize)) + .Returns(_readBufferSize); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalWriteLength((uint) _bufferSize, _handle)) + .Returns(_writeBufferSize); + } + + protected override async Task ActAsync() + { + _target = await SftpFileStream.OpenAsync(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize, _cancellationToken); + } + + [TestMethod] + public void CanReadShouldReturnTrue() + { + Assert.IsTrue(_target.CanRead); + } + + [TestMethod] + public void CanSeekShouldReturnTrue() + { + Assert.IsTrue(_target.CanSeek); + } + + [TestMethod] + public void CanWriteShouldReturnTrue() + { + Assert.IsTrue(_target.CanWrite); + } + + [TestMethod] + public void CanTimeoutShouldReturnTrue() + { + Assert.IsTrue(_target.CanTimeout); + } + + [TestMethod] + public void PositionShouldReturnZero() + { + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + var actual = _target.Position; + + Assert.AreEqual(0L, actual); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + } + + [TestMethod] + public async Task ReadShouldStartReadingAtBeginningOfFile() + { + var buffer = new byte[8]; + var data = new byte[] { 5, 4, 3, 2, 1 }; + var expected = new byte[] { 0, 5, 4, 3, 2, 1, 0, 0 }; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence).Setup(p => p.RequestReadAsync(_handle, 0UL, _readBufferSize, _cancellationToken)).ReturnsAsync(data); + + var actual = await _target.ReadAsync(buffer, 1, data.Length, _cancellationToken); + + Assert.AreEqual(data.Length, actual); + Assert.IsTrue(buffer.IsEqualTo(expected)); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + SftpSessionMock.Verify(p => p.RequestReadAsync(_handle, 0UL, _readBufferSize, _cancellationToken), Times.Once); + } + + [TestMethod] + public async Task WriteShouldStartWritingAtBeginningOfFile() + { + var buffer = new byte[_writeBufferSize]; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence).Setup(p => p.RequestWriteAsync(_handle, 0UL, buffer, 0, buffer.Length, _cancellationToken)).Returns(Task.CompletedTask); + + await _target.WriteAsync(buffer, 0, buffer.Length, _cancellationToken); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + SftpSessionMock.Verify(p => p.RequestWriteAsync(_handle, 0UL, buffer, 0, buffer.Length, _cancellationToken), Times.Once); + } + + [TestMethod] + public void RequestOpenOnSftpSessionShouldBeInvokedOnce() + { + SftpSessionMock.Verify(p => p.RequestOpenAsync(_path, Flags.Read | Flags.Write | Flags.CreateNew, _cancellationToken), Times.Once); + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreateNew_FileAccessWrite.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreateNew_FileAccessWrite.cs new file mode 100644 index 000000000..7671fe300 --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreateNew_FileAccessWrite.cs @@ -0,0 +1,136 @@ +#if FEATURE_TAP +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Sftp; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_OpenAsync_FileModeCreateNew_FileAccessWrite : SftpFileStreamAsyncTestBase + { + private Random _random; + private string _path; + private FileMode _fileMode; + private FileAccess _fileAccess; + private int _bufferSize; + private uint _readBufferSize; + private uint _writeBufferSize; + private byte[] _handle; + private SftpFileStream _target; + private CancellationToken _cancellationToken; + + protected override void SetupData() + { + base.SetupData(); + + _random = new Random(); + _path = _random.Next().ToString(); + _fileMode = FileMode.CreateNew; + _fileAccess = FileAccess.Write; + _bufferSize = _random.Next(5, 1000); + _readBufferSize = (uint) _random.Next(5, 1000); + _writeBufferSize = (uint) _random.Next(5, 1000); + _handle = GenerateRandom(_random.Next(1, 10), _random); + _cancellationToken = new CancellationToken(); + } + + protected override void SetupMocks() + { + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestOpenAsync(_path, Flags.Write | Flags.CreateNew, _cancellationToken)) + .ReturnsAsync(_handle); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalReadLength((uint) _bufferSize)) + .Returns(_readBufferSize); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalWriteLength((uint) _bufferSize, _handle)) + .Returns(_writeBufferSize); + } + + protected override async Task ActAsync() + { + _target = await SftpFileStream.OpenAsync(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize, _cancellationToken); + } + + [TestMethod] + public void CanReadShouldReturnFalse() + { + Assert.IsFalse(_target.CanRead); + } + + [TestMethod] + public void CanSeekShouldReturnTrue() + { + Assert.IsTrue(_target.CanSeek); + } + + [TestMethod] + public void CanWriteShouldReturnTrue() + { + Assert.IsTrue(_target.CanWrite); + } + + [TestMethod] + public void CanTimeoutShouldReturnTrue() + { + Assert.IsTrue(_target.CanTimeout); + } + + [TestMethod] + public void PositionShouldReturnZero() + { + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + var actual = _target.Position; + + Assert.AreEqual(0L, actual); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + } + + [TestMethod] + public async Task ReadShouldThrowNotSupportedException() + { + var buffer = new byte[_readBufferSize]; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + try + { + await _target.ReadAsync(buffer, 0, buffer.Length); + Assert.Fail(); + } + catch (NotSupportedException ex) + { + Assert.IsNull(ex.InnerException); + } + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + } + + [TestMethod] + public async Task WriteShouldStartWritingAtBeginningOfFile() + { + var buffer = new byte[_writeBufferSize]; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence).Setup(p => p.RequestWriteAsync(_handle, 0UL, buffer, 0, buffer.Length, _cancellationToken)).Returns(Task.CompletedTask); + + await _target.WriteAsync(buffer, 0, buffer.Length); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + SftpSessionMock.Verify(p => p.RequestWriteAsync(_handle, 0UL, buffer, 0, buffer.Length, _cancellationToken), Times.Once); + } + + [TestMethod] + public void RequestOpenOnSftpSessionShouldBeInvokedOnce() + { + SftpSessionMock.Verify(p => p.RequestOpenAsync(_path, Flags.Write | Flags.CreateNew, _cancellationToken), Times.Once); + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessRead.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessRead.cs new file mode 100644 index 000000000..2c6d28a6e --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessRead.cs @@ -0,0 +1,58 @@ +#if FEATURE_TAP +using System; +using System.IO; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Renci.SshNet.Sftp; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessRead : SftpFileStreamAsyncTestBase + { + private Random _random; + private string _path; + private FileMode _fileMode; + private FileAccess _fileAccess; + private int _bufferSize; + private ArgumentException _actualException; + + protected override void SetupData() + { + base.SetupData(); + + _random = new Random(); + _path = _random.Next().ToString(); + _fileMode = FileMode.Create; + _fileAccess = FileAccess.Read; + _bufferSize = _random.Next(5, 1000); + } + + protected override void SetupMocks() + { + } + + protected override async Task ActAsync() + { + try + { + await SftpFileStream.OpenAsync(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize, default); + Assert.Fail(); + } + catch (ArgumentException ex) + { + _actualException = ex; + } + } + + [TestMethod] + public void CtorShouldHaveThrownArgumentException() + { + Assert.IsNotNull(_actualException); + Assert.IsNull(_actualException.InnerException); + Assert.AreEqual(string.Format("Combining {0}: {1} with {2}: {3} is invalid.", typeof(FileMode).Name, _fileMode, typeof(FileAccess).Name, _fileAccess), _actualException.Message); + Assert.IsNull(_actualException.ParamName); + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessReadWrite_FileDoesNotExist.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessReadWrite_FileDoesNotExist.cs new file mode 100644 index 000000000..5fe519f17 --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessReadWrite_FileDoesNotExist.cs @@ -0,0 +1,136 @@ +#if FEATURE_TAP +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Common; +using Renci.SshNet.Sftp; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessReadWrite_FileDoesNotExist : SftpFileStreamAsyncTestBase + { + private Random _random; + private string _path; + private FileMode _fileMode; + private FileAccess _fileAccess; + private int _bufferSize; + private uint _readBufferSize; + private uint _writeBufferSize; + private byte[] _handle; + private SftpFileStream _target; + private CancellationToken _cancellationToken; + + protected override void SetupData() + { + base.SetupData(); + + _random = new Random(); + _path = _random.Next().ToString(); + _fileMode = FileMode.Create; + _fileAccess = FileAccess.ReadWrite; + _bufferSize = _random.Next(5, 1000); + _readBufferSize = (uint)_random.Next(5, 1000); + _writeBufferSize = (uint)_random.Next(5, 1000); + _handle = GenerateRandom(_random.Next(1, 10), _random); + _cancellationToken = new CancellationToken(); + } + + protected override void SetupMocks() + { + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestOpenAsync(_path, Flags.Read | Flags.Write | Flags.CreateNewOrOpen | Flags.Truncate, _cancellationToken)) + .ReturnsAsync(_handle); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalReadLength((uint) _bufferSize)) + .Returns(_readBufferSize); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalWriteLength((uint) _bufferSize, _handle)) + .Returns(_writeBufferSize); + } + + protected override async Task ActAsync() + { + _target = await SftpFileStream.OpenAsync(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize, _cancellationToken); + } + + [TestMethod] + public void CanReadShouldReturnTrue() + { + Assert.IsTrue(_target.CanRead); + } + + [TestMethod] + public void CanSeekShouldReturnTrue() + { + Assert.IsTrue(_target.CanSeek); + } + + [TestMethod] + public void CanWriteShouldReturnTrue() + { + Assert.IsTrue(_target.CanWrite); + } + + [TestMethod] + public void CanTimeoutShouldReturnTrue() + { + Assert.IsTrue(_target.CanTimeout); + } + + [TestMethod] + public void PositionShouldReturnZero() + { + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + var actual = _target.Position; + + Assert.AreEqual(0L, actual); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + } + + [TestMethod] + public async Task ReadShouldStartReadingAtBeginningOfFile() + { + var buffer = new byte[8]; + var data = new byte[] { 5, 4, 3, 2, 1 }; + var expected = new byte[] { 0, 5, 4, 3, 2, 1, 0, 0 }; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence).Setup(p => p.RequestReadAsync(_handle, 0UL, _readBufferSize, _cancellationToken)).ReturnsAsync(data); + + var actual = await _target.ReadAsync(buffer, 1, data.Length); + + Assert.AreEqual(data.Length, actual); + Assert.IsTrue(buffer.IsEqualTo(expected)); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + SftpSessionMock.Verify(p => p.RequestReadAsync(_handle, 0UL, _readBufferSize, _cancellationToken), Times.Once); + } + + [TestMethod] + public async Task WriteShouldStartWritingAtBeginningOfFile() + { + var buffer = new byte[_writeBufferSize]; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence).Setup(p => p.RequestWriteAsync(_handle, 0UL, buffer, 0, buffer.Length, _cancellationToken)).Returns(Task.CompletedTask); + + await _target.WriteAsync(buffer, 0, buffer.Length); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + SftpSessionMock.Verify(p => p.RequestWriteAsync(_handle, 0UL, buffer, 0, buffer.Length, _cancellationToken), Times.Once); + } + + [TestMethod] + public void RequestOpenOnSftpSessionShouldBeInvokedOnce() + { + SftpSessionMock.Verify(p => p.RequestOpenAsync(_path, Flags.Read | Flags.Write | Flags.CreateNewOrOpen | Flags.Truncate, _cancellationToken), Times.Once); + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessReadWrite_FileExists.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessReadWrite_FileExists.cs new file mode 100644 index 000000000..a313afb96 --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessReadWrite_FileExists.cs @@ -0,0 +1,136 @@ +#if FEATURE_TAP +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Common; +using Renci.SshNet.Sftp; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessReadWrite_FileExists : SftpFileStreamAsyncTestBase + { + private Random _random; + private string _path; + private FileMode _fileMode; + private FileAccess _fileAccess; + private int _bufferSize; + private uint _readBufferSize; + private uint _writeBufferSize; + private byte[] _handle; + private SftpFileStream _target; + private CancellationToken _cancellationToken; + + protected override void SetupData() + { + base.SetupData(); + + _random = new Random(); + _path = _random.Next().ToString(); + _fileMode = FileMode.Create; + _fileAccess = FileAccess.ReadWrite; + _bufferSize = _random.Next(5, 1000); + _readBufferSize = (uint)_random.Next(5, 1000); + _writeBufferSize = (uint)_random.Next(5, 1000); + _handle = GenerateRandom(_random.Next(1, 10), _random); + _cancellationToken = new CancellationToken(); + } + + protected override void SetupMocks() + { + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestOpenAsync(_path, Flags.Read | Flags.Write | Flags.CreateNewOrOpen | Flags.Truncate, _cancellationToken)) + .ReturnsAsync(_handle); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalReadLength((uint) _bufferSize)) + .Returns(_readBufferSize); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalWriteLength((uint) _bufferSize, _handle)) + .Returns(_writeBufferSize); + } + + protected override async Task ActAsync() + { + _target = await SftpFileStream.OpenAsync(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize, _cancellationToken); + } + + [TestMethod] + public void CanReadShouldReturnTrue() + { + Assert.IsTrue(_target.CanRead); + } + + [TestMethod] + public void CanSeekShouldReturnTrue() + { + Assert.IsTrue(_target.CanSeek); + } + + [TestMethod] + public void CanWriteShouldReturnTrue() + { + Assert.IsTrue(_target.CanWrite); + } + + [TestMethod] + public void CanTimeoutShouldReturnTrue() + { + Assert.IsTrue(_target.CanTimeout); + } + + [TestMethod] + public void PositionShouldReturnZero() + { + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + var actual = _target.Position; + + Assert.AreEqual(0L, actual); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + } + + [TestMethod] + public async Task ReadShouldStartReadingAtBeginningOfFile() + { + var buffer = new byte[8]; + var data = new byte[] { 5, 4, 3, 2, 1 }; + var expected = new byte[] { 0, 5, 4, 3, 2, 1, 0, 0 }; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence).Setup(p => p.RequestReadAsync(_handle, 0UL, _readBufferSize, _cancellationToken)).ReturnsAsync(data); + + var actual = await _target.ReadAsync(buffer, 1, data.Length); + + Assert.AreEqual(data.Length, actual); + Assert.IsTrue(buffer.IsEqualTo(expected)); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + SftpSessionMock.Verify(p => p.RequestReadAsync(_handle, 0UL, _readBufferSize, _cancellationToken), Times.Once); + } + + [TestMethod] + public async Task WriteShouldStartWritingAtBeginningOfFile() + { + var buffer = new byte[_writeBufferSize]; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence).Setup(p => p.RequestWriteAsync(_handle, 0UL, buffer, 0, buffer.Length, _cancellationToken)).Returns(Task.CompletedTask); + + await _target.WriteAsync(buffer, 0, buffer.Length); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + SftpSessionMock.Verify(p => p.RequestWriteAsync(_handle, 0UL, buffer, 0, buffer.Length, _cancellationToken), Times.Once); + } + + [TestMethod] + public void RequestOpenOnSftpSessionShouldBeInvokedOnce() + { + SftpSessionMock.Verify(p => p.RequestOpenAsync(_path, Flags.Read | Flags.Write | Flags.CreateNewOrOpen | Flags.Truncate, _cancellationToken), Times.Once); + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessWrite_FileDoesNotExist.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessWrite_FileDoesNotExist.cs new file mode 100644 index 000000000..c1d7fc960 --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessWrite_FileDoesNotExist.cs @@ -0,0 +1,136 @@ +#if FEATURE_TAP +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Sftp; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessWrite_FileDoesNotExist : SftpFileStreamAsyncTestBase + { + private Random _random; + private string _path; + private FileMode _fileMode; + private FileAccess _fileAccess; + private int _bufferSize; + private uint _readBufferSize; + private uint _writeBufferSize; + private byte[] _handle; + private SftpFileStream _target; + private CancellationToken _cancellationToken; + + protected override void SetupData() + { + base.SetupData(); + + _random = new Random(); + _path = _random.Next().ToString(); + _fileMode = FileMode.Create; + _fileAccess = FileAccess.Write; + _bufferSize = _random.Next(5, 1000); + _readBufferSize = (uint)_random.Next(5, 1000); + _writeBufferSize = (uint)_random.Next(5, 1000); + _handle = GenerateRandom(_random.Next(1, 10), _random); + _cancellationToken = new CancellationToken(); + } + + protected override void SetupMocks() + { + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestOpenAsync(_path, Flags.Write | Flags.CreateNewOrOpen | Flags.Truncate, _cancellationToken)) + .ReturnsAsync(_handle); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalReadLength((uint) _bufferSize)) + .Returns(_readBufferSize); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalWriteLength((uint) _bufferSize, _handle)) + .Returns(_writeBufferSize); + } + + protected override async Task ActAsync() + { + _target = await SftpFileStream.OpenAsync(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize, _cancellationToken); + } + + [TestMethod] + public void CanReadShouldReturnFalse() + { + Assert.IsFalse(_target.CanRead); + } + + [TestMethod] + public void CanSeekShouldReturnTrue() + { + Assert.IsTrue(_target.CanSeek); + } + + [TestMethod] + public void CanWriteShouldReturnTrue() + { + Assert.IsTrue(_target.CanWrite); + } + + [TestMethod] + public void CanTimeoutShouldReturnTrue() + { + Assert.IsTrue(_target.CanTimeout); + } + + [TestMethod] + public void PositionShouldReturnZero() + { + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + var actual = _target.Position; + + Assert.AreEqual(0L, actual); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + } + + [TestMethod] + public async Task ReadShouldThrowNotSupportedException() + { + var buffer = new byte[_readBufferSize]; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + try + { + await _target.ReadAsync(buffer, 0, buffer.Length); + Assert.Fail(); + } + catch (NotSupportedException ex) + { + Assert.IsNull(ex.InnerException); + } + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + } + + [TestMethod] + public async Task WriteShouldStartWritingAtBeginningOfFile() + { + var buffer = new byte[_writeBufferSize]; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence).Setup(p => p.RequestWriteAsync(_handle, 0UL, buffer, 0, buffer.Length, _cancellationToken)).Returns(Task.CompletedTask); + + await _target.WriteAsync(buffer, 0, buffer.Length); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + SftpSessionMock.Verify(p => p.RequestWriteAsync(_handle, 0UL, buffer, 0, buffer.Length, _cancellationToken), Times.Once); + } + + [TestMethod] + public void RequestOpenOnSftpSessionShouldBeInvokedOnceWithTruncateAndOnceWithCreateNew() + { + SftpSessionMock.Verify(p => p.RequestOpenAsync(_path, Flags.Write | Flags.CreateNewOrOpen | Flags.Truncate, _cancellationToken), Times.Once); + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessWrite_FileExists.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessWrite_FileExists.cs new file mode 100644 index 000000000..834299706 --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessWrite_FileExists.cs @@ -0,0 +1,136 @@ +#if FEATURE_TAP +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Sftp; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessWrite_FileExists : SftpFileStreamAsyncTestBase + { + private Random _random; + private string _path; + private FileMode _fileMode; + private FileAccess _fileAccess; + private int _bufferSize; + private uint _readBufferSize; + private uint _writeBufferSize; + private byte[] _handle; + private SftpFileStream _target; + private CancellationToken _cancellationToken; + + protected override void SetupData() + { + base.SetupData(); + + _random = new Random(); + _path = _random.Next().ToString(); + _fileMode = FileMode.Create; + _fileAccess = FileAccess.Write; + _bufferSize = _random.Next(5, 1000); + _readBufferSize = (uint) _random.Next(5, 1000); + _writeBufferSize = (uint) _random.Next(5, 1000); + _handle = GenerateRandom(_random.Next(1, 10), _random); + _cancellationToken = new CancellationToken(); + } + + protected override void SetupMocks() + { + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestOpenAsync(_path, Flags.Write | Flags.CreateNewOrOpen | Flags.Truncate, _cancellationToken)) + .ReturnsAsync(_handle); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalReadLength((uint) _bufferSize)) + .Returns(_readBufferSize); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalWriteLength((uint) _bufferSize, _handle)) + .Returns(_writeBufferSize); + } + + protected override async Task ActAsync() + { + _target = await SftpFileStream.OpenAsync(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize, _cancellationToken); + } + + [TestMethod] + public void CanReadShouldReturnFalse() + { + Assert.IsFalse(_target.CanRead); + } + + [TestMethod] + public void CanSeekShouldReturnTrue() + { + Assert.IsTrue(_target.CanSeek); + } + + [TestMethod] + public void CanWriteShouldReturnTrue() + { + Assert.IsTrue(_target.CanWrite); + } + + [TestMethod] + public void CanTimeoutShouldReturnTrue() + { + Assert.IsTrue(_target.CanTimeout); + } + + [TestMethod] + public void PositionShouldReturnZero() + { + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + var actual = _target.Position; + + Assert.AreEqual(0L, actual); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + } + + [TestMethod] + public async Task ReadShouldThrowNotSupportedException() + { + var buffer = new byte[_readBufferSize]; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + try + { + await _target.ReadAsync(buffer, 0, buffer.Length); + Assert.Fail(); + } + catch (NotSupportedException ex) + { + Assert.IsNull(ex.InnerException); + } + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + } + + [TestMethod] + public async Task WriteShouldStartWritingAtBeginningOfFile() + { + var buffer = new byte[_writeBufferSize]; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence).Setup(p => p.RequestWriteAsync(_handle, 0UL, buffer, 0, buffer.Length, _cancellationToken)).Returns(Task.CompletedTask); + + await _target.WriteAsync(buffer, 0, buffer.Length); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + SftpSessionMock.Verify(p => p.RequestWriteAsync(_handle, 0UL, buffer, 0, buffer.Length, _cancellationToken), Times.Once); + } + + [TestMethod] + public void RequestOpenOnSftpSessionShouldBeInvokedOnce() + { + SftpSessionMock.Verify(p => p.RequestOpenAsync(_path, Flags.Write | Flags.CreateNewOrOpen | Flags.Truncate, _cancellationToken), Times.Once); + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeInvalid.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeInvalid.cs new file mode 100644 index 000000000..9cfc4a37f --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeInvalid.cs @@ -0,0 +1,57 @@ +#if FEATURE_TAP +using System; +using System.IO; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Renci.SshNet.Sftp; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_OpenAsync_FileModeInvalid : SftpFileStreamAsyncTestBase + { + private Random _random; + private string _path; + private FileMode _fileMode; + private FileAccess _fileAccess; + private int _bufferSize; + private ArgumentOutOfRangeException _actualException; + + protected override void SetupData() + { + base.SetupData(); + + _random = new Random(); + _path = _random.Next().ToString(); + _fileMode = 0; + _fileAccess = FileAccess.Read; + _bufferSize = _random.Next(5, 1000); + } + + protected override void SetupMocks() + { + } + + protected override async Task ActAsync() + { + try + { + await SftpFileStream.OpenAsync(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize, default); + Assert.Fail(); + } + catch (ArgumentOutOfRangeException ex) + { + _actualException = ex; + } + } + + [TestMethod] + public void CtorShouldHaveThrownArgumentException() + { + Assert.IsNotNull(_actualException); + Assert.IsNull(_actualException.InnerException); + Assert.AreEqual("mode", _actualException.ParamName); + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpenOrCreate_FileAccessRead.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpenOrCreate_FileAccessRead.cs new file mode 100644 index 000000000..f9360c40c --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpenOrCreate_FileAccessRead.cs @@ -0,0 +1,141 @@ +#if FEATURE_TAP +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Common; +using Renci.SshNet.Sftp; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_OpenAsync_FileModeOpenOrCreate_FileAccessRead : SftpFileStreamAsyncTestBase + { + private Random _random; + private string _path; + private FileMode _fileMode; + private FileAccess _fileAccess; + private int _bufferSize; + private uint _readBufferSize; + private uint _writeBufferSize; + private byte[] _handle; + private SftpFileStream _target; + private CancellationToken _cancellationToken; + + protected override void SetupData() + { + base.SetupData(); + + _random = new Random(); + _path = _random.Next().ToString(); + _fileMode = FileMode.OpenOrCreate; + _fileAccess = FileAccess.Read; + _bufferSize = _random.Next(5, 1000); + _readBufferSize = (uint) _random.Next(5, 1000); + _writeBufferSize = (uint) _random.Next(5, 1000); + _handle = GenerateRandom(_random.Next(1, 10), _random); + _cancellationToken = new CancellationToken(); + } + + protected override void SetupMocks() + { + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestOpenAsync(_path, Flags.Read | Flags.CreateNewOrOpen, _cancellationToken)) + .ReturnsAsync(_handle); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalReadLength((uint) _bufferSize)) + .Returns(_readBufferSize); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalWriteLength((uint) _bufferSize, _handle)) + .Returns(_writeBufferSize); + } + + protected override async Task ActAsync() + { + _target = await SftpFileStream.OpenAsync(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize, _cancellationToken); + } + + [TestMethod] + public void CanReadShouldReturnTrue() + { + Assert.IsTrue(_target.CanRead); + } + + [TestMethod] + public void CanSeekShouldReturnTrue() + { + Assert.IsTrue(_target.CanSeek); + } + + [TestMethod] + public void CanWriteShouldReturnFalse() + { + Assert.IsFalse(_target.CanWrite); + } + + [TestMethod] + public void CanTimeoutShouldReturnTrue() + { + Assert.IsTrue(_target.CanTimeout); + } + + [TestMethod] + public void PositionShouldReturnZero() + { + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + var actual = _target.Position; + + Assert.AreEqual(0L, actual); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + } + + [TestMethod] + public async Task ReadShouldStartReadingAtBeginningOfFile() + { + var buffer = new byte[8]; + var data = new byte[] { 5, 4, 3, 2, 1 }; + var expected = new byte[] { 0, 5, 4, 3, 2, 1, 0, 0 }; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence).Setup(p => p.RequestReadAsync(_handle, 0UL, _readBufferSize, _cancellationToken)).ReturnsAsync(data); + + var actual = await _target.ReadAsync(buffer, 1, data.Length); + + Assert.AreEqual(data.Length, actual); + Assert.IsTrue(buffer.IsEqualTo(expected)); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + SftpSessionMock.Verify(p => p.RequestReadAsync(_handle, 0UL, _readBufferSize, _cancellationToken), Times.Once); + } + + [TestMethod] + public async Task WriteShouldThrowNotSupportedException() + { + var buffer = new byte[_writeBufferSize]; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + try + { + await _target.WriteAsync(buffer, 0, buffer.Length); + } + catch (NotSupportedException ex) + { + Assert.IsNull(ex.InnerException); + } + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + } + + [TestMethod] + public void RequestOpenOnSftpSessionShouldBeInvokedOnce() + { + SftpSessionMock.Verify(p => p.RequestOpenAsync(_path, Flags.Read | Flags.CreateNewOrOpen, _cancellationToken), Times.Once); + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpenOrCreate_FileAccessReadWrite.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpenOrCreate_FileAccessReadWrite.cs new file mode 100644 index 000000000..7e5e4d867 --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpenOrCreate_FileAccessReadWrite.cs @@ -0,0 +1,136 @@ +#if FEATURE_TAP +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Common; +using Renci.SshNet.Sftp; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_OpenAsync_FileModeOpenOrCreate_FileAccessReadWrite : SftpFileStreamAsyncTestBase + { + private Random _random; + private string _path; + private FileMode _fileMode; + private FileAccess _fileAccess; + private int _bufferSize; + private uint _readBufferSize; + private uint _writeBufferSize; + private byte[] _handle; + private SftpFileStream _target; + private CancellationToken _cancellationToken; + + protected override void SetupData() + { + base.SetupData(); + + _random = new Random(); + _path = _random.Next().ToString(); + _fileMode = FileMode.OpenOrCreate; + _fileAccess = FileAccess.ReadWrite; + _bufferSize = _random.Next(5, 1000); + _readBufferSize = (uint)_random.Next(5, 1000); + _writeBufferSize = (uint)_random.Next(5, 1000); + _handle = GenerateRandom(_random.Next(1, 10), _random); + _cancellationToken = new CancellationToken(); + } + + protected override void SetupMocks() + { + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestOpenAsync(_path, Flags.Read | Flags.Write | Flags.CreateNewOrOpen, _cancellationToken)) + .ReturnsAsync(_handle); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalReadLength((uint) _bufferSize)) + .Returns(_readBufferSize); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalWriteLength((uint) _bufferSize, _handle)) + .Returns(_writeBufferSize); + } + + protected override async Task ActAsync() + { + _target = await SftpFileStream.OpenAsync(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize, _cancellationToken); + } + + [TestMethod] + public void CanReadShouldReturnTrue() + { + Assert.IsTrue(_target.CanRead); + } + + [TestMethod] + public void CanSeekShouldReturnTrue() + { + Assert.IsTrue(_target.CanSeek); + } + + [TestMethod] + public void CanWriteShouldReturnTrue() + { + Assert.IsTrue(_target.CanWrite); + } + + [TestMethod] + public void CanTimeoutShouldReturnTrue() + { + Assert.IsTrue(_target.CanTimeout); + } + + [TestMethod] + public void PositionShouldReturnZero() + { + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + var actual = _target.Position; + + Assert.AreEqual(0L, actual); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + } + + [TestMethod] + public async Task ReadShouldStartReadingAtBeginningOfFile() + { + var buffer = new byte[8]; + var data = new byte[] { 5, 4, 3, 2, 1 }; + var expected = new byte[] { 0, 5, 4, 3, 2, 1, 0, 0 }; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence).Setup(p => p.RequestReadAsync(_handle, 0UL, _readBufferSize, _cancellationToken)).ReturnsAsync(data); + + var actual = await _target.ReadAsync(buffer, 1, data.Length); + + Assert.AreEqual(data.Length, actual); + Assert.IsTrue(buffer.IsEqualTo(expected)); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + SftpSessionMock.Verify(p => p.RequestReadAsync(_handle, 0UL, _readBufferSize, _cancellationToken), Times.Once); + } + + [TestMethod] + public async Task WriteShouldStartWritingAtBeginningOfFile() + { + var buffer = new byte[_writeBufferSize]; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence).Setup(p => p.RequestWriteAsync(_handle, 0UL, buffer, 0, buffer.Length, _cancellationToken)).Returns(Task.CompletedTask); + + await _target.WriteAsync(buffer, 0, buffer.Length); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + SftpSessionMock.Verify(p => p.RequestWriteAsync(_handle, 0UL, buffer, 0, buffer.Length, _cancellationToken), Times.Once); + } + + [TestMethod] + public void RequestOpenOnSftpSessionShouldBeInvokedOnce() + { + SftpSessionMock.Verify(p => p.RequestOpenAsync(_path, Flags.Read | Flags.Write | Flags.CreateNewOrOpen, _cancellationToken), Times.Once); + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpenOrCreate_FileAccessWrite.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpenOrCreate_FileAccessWrite.cs new file mode 100644 index 000000000..edccf9b99 --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpenOrCreate_FileAccessWrite.cs @@ -0,0 +1,136 @@ +#if FEATURE_TAP +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Sftp; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_OpenAsync_FileModeOpenOrCreate_FileAccessWrite : SftpFileStreamAsyncTestBase + { + private Random _random; + private string _path; + private FileMode _fileMode; + private FileAccess _fileAccess; + private int _bufferSize; + private uint _readBufferSize; + private uint _writeBufferSize; + private byte[] _handle; + private SftpFileStream _target; + private CancellationToken _cancellationToken; + + protected override void SetupData() + { + base.SetupData(); + + _random = new Random(); + _path = _random.Next().ToString(); + _fileMode = FileMode.OpenOrCreate; + _fileAccess = FileAccess.Write; + _bufferSize = _random.Next(5, 1000); + _readBufferSize = (uint) _random.Next(5, 1000); + _writeBufferSize = (uint) _random.Next(5, 1000); + _handle = GenerateRandom(_random.Next(1, 10), _random); + _cancellationToken = new CancellationToken(); + } + + protected override void SetupMocks() + { + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestOpenAsync(_path, Flags.Write | Flags.CreateNewOrOpen, _cancellationToken)) + .ReturnsAsync(_handle); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalReadLength((uint) _bufferSize)) + .Returns(_readBufferSize); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalWriteLength((uint) _bufferSize, _handle)) + .Returns(_writeBufferSize); + } + + protected override async Task ActAsync() + { + _target = await SftpFileStream.OpenAsync(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize, _cancellationToken); + } + + [TestMethod] + public void CanReadShouldReturnFalse() + { + Assert.IsFalse(_target.CanRead); + } + + [TestMethod] + public void CanSeekShouldReturnTrue() + { + Assert.IsTrue(_target.CanSeek); + } + + [TestMethod] + public void CanWriteShouldReturnTrue() + { + Assert.IsTrue(_target.CanWrite); + } + + [TestMethod] + public void CanTimeoutShouldReturnTrue() + { + Assert.IsTrue(_target.CanTimeout); + } + + [TestMethod] + public void PositionShouldReturnZero() + { + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + var actual = _target.Position; + + Assert.AreEqual(0L, actual); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + } + + [TestMethod] + public async Task ReadShouldThrowNotSupportedException() + { + var buffer = new byte[_readBufferSize]; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + try + { + await _target.ReadAsync(buffer, 0, buffer.Length); + Assert.Fail(); + } + catch (NotSupportedException ex) + { + Assert.IsNull(ex.InnerException); + } + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + } + + [TestMethod] + public async Task WriteShouldStartWritingAtBeginningOfFile() + { + var buffer = new byte[_writeBufferSize]; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence).Setup(p => p.RequestWriteAsync(_handle, 0UL, buffer, 0, buffer.Length, _cancellationToken)).Returns(Task.CompletedTask); + + await _target.WriteAsync(buffer, 0, buffer.Length); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + SftpSessionMock.Verify(p => p.RequestWriteAsync(_handle, 0UL, buffer, 0, buffer.Length, _cancellationToken), Times.Once); + } + + [TestMethod] + public void RequestOpenOnSftpSessionShouldBeInvokedOnce() + { + SftpSessionMock.Verify(p => p.RequestOpenAsync(_path, Flags.Write | Flags.CreateNewOrOpen, _cancellationToken), Times.Once); + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpen_FileAccessRead.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpen_FileAccessRead.cs new file mode 100644 index 000000000..1d4f686fa --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpen_FileAccessRead.cs @@ -0,0 +1,142 @@ +#if FEATURE_TAP +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Common; +using Renci.SshNet.Sftp; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_OpenAsync_FileModeOpen_FileAccessRead : SftpFileStreamAsyncTestBase + { + private Random _random; + private string _path; + private FileMode _fileMode; + private FileAccess _fileAccess; + private int _bufferSize; + private uint _readBufferSize; + private uint _writeBufferSize; + private byte[] _handle; + private SftpFileStream _target; + private CancellationToken _cancellationToken; + + protected override void SetupData() + { + base.SetupData(); + + _random = new Random(); + _path = _random.Next().ToString(); + _fileMode = FileMode.Open; + _fileAccess = FileAccess.Read; + _bufferSize = _random.Next(5, 1000); + _readBufferSize = (uint)_random.Next(5, 1000); + _writeBufferSize = (uint)_random.Next(5, 1000); + _handle = GenerateRandom(_random.Next(1, 10), _random); + _cancellationToken = new CancellationToken(); + } + + protected override void SetupMocks() + { + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestOpenAsync(_path, Flags.Read, _cancellationToken)) + .ReturnsAsync(_handle); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalReadLength((uint) _bufferSize)) + .Returns(_readBufferSize); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalWriteLength((uint) _bufferSize, _handle)) + .Returns(_writeBufferSize); + } + + protected override async Task ActAsync() + { + _target = await SftpFileStream.OpenAsync(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize, _cancellationToken); + } + + [TestMethod] + public void CanReadShouldReturnTrue() + { + Assert.IsTrue(_target.CanRead); + } + + [TestMethod] + public void CanSeekShouldReturnTrue() + { + Assert.IsTrue(_target.CanSeek); + } + + [TestMethod] + public void CanWriteShouldReturnFalse() + { + Assert.IsFalse(_target.CanWrite); + } + + [TestMethod] + public void CanTimeoutShouldReturnTrue() + { + Assert.IsTrue(_target.CanTimeout); + } + + [TestMethod] + public void PositionShouldReturnZero() + { + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + var actual = _target.Position; + + Assert.AreEqual(0L, actual); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + } + + [TestMethod] + public async Task ReadShouldStartReadingAtBeginningOfFile() + { + var buffer = new byte[8]; + var data = new byte[] { 5, 4, 3, 2, 1 }; + var expected = new byte[] { 0, 5, 4, 3, 2, 1, 0, 0 }; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence).Setup(p => p.RequestReadAsync(_handle, 0UL, _readBufferSize, _cancellationToken)).ReturnsAsync(data); + + var actual = await _target.ReadAsync(buffer, 1, data.Length, _cancellationToken); + + Assert.AreEqual(data.Length, actual); + Assert.IsTrue(buffer.IsEqualTo(expected)); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + SftpSessionMock.Verify(p => p.RequestReadAsync(_handle, 0UL, _readBufferSize, _cancellationToken), Times.Once); + } + + [TestMethod] + public async Task WriteShouldThrowNotSupportedException() + { + var buffer = new byte[_writeBufferSize]; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + try + { + await _target.WriteAsync(buffer, 0, buffer.Length, _cancellationToken); + } + catch (NotSupportedException ex) + { + Assert.IsNull(ex.InnerException); + Assert.AreEqual("Write not supported.", ex.Message); + } + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + } + + [TestMethod] + public void RequestOpenOnSftpSessionShouldBeInvokedOnce() + { + SftpSessionMock.Verify(p => p.RequestOpenAsync(_path, Flags.Read, _cancellationToken), Times.Once); + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpen_FileAccessReadWrite.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpen_FileAccessReadWrite.cs new file mode 100644 index 000000000..8ee641337 --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpen_FileAccessReadWrite.cs @@ -0,0 +1,136 @@ +#if FEATURE_TAP +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Common; +using Renci.SshNet.Sftp; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_OpenAsync_FileModeOpen_FileAccessReadWrite : SftpFileStreamAsyncTestBase + { + private Random _random; + private string _path; + private FileMode _fileMode; + private FileAccess _fileAccess; + private int _bufferSize; + private uint _readBufferSize; + private uint _writeBufferSize; + private byte[] _handle; + private SftpFileStream _target; + private CancellationToken _cancellationToken; + + protected override void SetupData() + { + base.SetupData(); + + _random = new Random(); + _path = _random.Next().ToString(); + _fileMode = FileMode.Open; + _fileAccess = FileAccess.ReadWrite; + _bufferSize = _random.Next(5, 1000); + _readBufferSize = (uint) _random.Next(5, 1000); + _writeBufferSize = (uint) _random.Next(5, 1000); + _handle = GenerateRandom(_random.Next(1, 10), _random); + _cancellationToken = new CancellationToken(); + } + + protected override void SetupMocks() + { + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestOpenAsync(_path, Flags.Read | Flags.Write, _cancellationToken)) + .ReturnsAsync(_handle); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalReadLength((uint) _bufferSize)) + .Returns(_readBufferSize); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalWriteLength((uint) _bufferSize, _handle)) + .Returns(_writeBufferSize); + } + + protected override async Task ActAsync() + { + _target = await SftpFileStream.OpenAsync(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize, _cancellationToken); + } + + [TestMethod] + public void CanReadShouldReturnTrue() + { + Assert.IsTrue(_target.CanRead); + } + + [TestMethod] + public void CanSeekShouldReturnTrue() + { + Assert.IsTrue(_target.CanSeek); + } + + [TestMethod] + public void CanWriteShouldReturnTrue() + { + Assert.IsTrue(_target.CanWrite); + } + + [TestMethod] + public void CanTimeoutShouldReturnTrue() + { + Assert.IsTrue(_target.CanTimeout); + } + + [TestMethod] + public void PositionShouldReturnZero() + { + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + var actual = _target.Position; + + Assert.AreEqual(0L, actual); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + } + + [TestMethod] + public async Task ReadShouldStartReadingAtBeginningOfFile() + { + var buffer = new byte[8]; + var data = new byte[] { 5, 4, 3, 2, 1 }; + var expected = new byte[] { 0, 5, 4, 3, 2, 1, 0, 0 }; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence).Setup(p => p.RequestReadAsync(_handle, 0UL, _readBufferSize, _cancellationToken)).ReturnsAsync(data); + + var actual = await _target.ReadAsync(buffer, 1, data.Length); + + Assert.AreEqual(data.Length, actual); + Assert.IsTrue(buffer.IsEqualTo(expected)); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + SftpSessionMock.Verify(p => p.RequestReadAsync(_handle, 0UL, _readBufferSize, _cancellationToken), Times.Once); + } + + [TestMethod] + public async Task WriteShouldStartWritingAtBeginningOfFile() + { + var buffer = new byte[_writeBufferSize]; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence).Setup(p => p.RequestWriteAsync(_handle, 0UL, buffer, 0, buffer.Length, _cancellationToken)).Returns(Task.CompletedTask); + + await _target.WriteAsync(buffer, 0, buffer.Length); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + SftpSessionMock.Verify(p => p.RequestWriteAsync(_handle, 0UL, buffer, 0, buffer.Length, _cancellationToken), Times.Once); + } + + [TestMethod] + public void RequestOpenOnSftpSessionShouldBeInvokedOnce() + { + SftpSessionMock.Verify(p => p.RequestOpenAsync(_path, Flags.Read | Flags.Write, _cancellationToken), Times.Once); + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpen_FileAccessWrite.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpen_FileAccessWrite.cs new file mode 100644 index 000000000..4be281731 --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpen_FileAccessWrite.cs @@ -0,0 +1,136 @@ +#if FEATURE_TAP +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Sftp; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_OpenAsync_FileModeOpen_FileAccessWrite : SftpFileStreamAsyncTestBase + { + private Random _random; + private string _path; + private FileMode _fileMode; + private FileAccess _fileAccess; + private int _bufferSize; + private uint _readBufferSize; + private uint _writeBufferSize; + private byte[] _handle; + private SftpFileStream _target; + private CancellationToken _cancellationToken; + + protected override void SetupData() + { + base.SetupData(); + + _random = new Random(); + _path = _random.Next().ToString(); + _fileMode = FileMode.Open; + _fileAccess = FileAccess.Write; + _bufferSize = _random.Next(5, 1000); + _readBufferSize = (uint) _random.Next(5, 1000); + _writeBufferSize = (uint) _random.Next(5, 1000); + _handle = GenerateRandom(_random.Next(1, 10), _random); + _cancellationToken = new CancellationToken(); + } + + protected override void SetupMocks() + { + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestOpenAsync(_path, Flags.Write, _cancellationToken)) + .ReturnsAsync(_handle); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalReadLength((uint) _bufferSize)) + .Returns(_readBufferSize); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalWriteLength((uint) _bufferSize, _handle)) + .Returns(_writeBufferSize); + } + + protected override async Task ActAsync() + { + _target = await SftpFileStream.OpenAsync(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize, _cancellationToken); + } + + [TestMethod] + public void CanReadShouldReturnFalse() + { + Assert.IsFalse(_target.CanRead); + } + + [TestMethod] + public void CanSeekShouldReturnTrue() + { + Assert.IsTrue(_target.CanSeek); + } + + [TestMethod] + public void CanWriteShouldReturnTrue() + { + Assert.IsTrue(_target.CanWrite); + } + + [TestMethod] + public void CanTimeoutShouldReturnTrue() + { + Assert.IsTrue(_target.CanTimeout); + } + + [TestMethod] + public void PositionShouldReturnZero() + { + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + var actual = _target.Position; + + Assert.AreEqual(0L, actual); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + } + + [TestMethod] + public async Task ReadShouldThrowNotSupportedException() + { + var buffer = new byte[_readBufferSize]; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + try + { + await _target.ReadAsync(buffer, 0, buffer.Length); + Assert.Fail(); + } + catch (NotSupportedException ex) + { + Assert.IsNull(ex.InnerException); + } + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + } + + [TestMethod] + public async Task WriteShouldStartWritingAtBeginningOfFile() + { + var buffer = new byte[_writeBufferSize]; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence).Setup(p => p.RequestWriteAsync(_handle, 0UL, buffer, 0, buffer.Length, _cancellationToken)).Returns(Task.CompletedTask); + + await _target.WriteAsync(buffer, 0, buffer.Length); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + SftpSessionMock.Verify(p => p.RequestWriteAsync(_handle, 0UL, buffer, 0, buffer.Length, _cancellationToken), Times.Once); + } + + [TestMethod] + public void RequestOpenOnSftpSessionShouldBeInvokedOnce() + { + SftpSessionMock.Verify(p => p.RequestOpenAsync(_path, Flags.Write, _cancellationToken), Times.Once); + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeTruncate_FileAccessRead.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeTruncate_FileAccessRead.cs new file mode 100644 index 000000000..9883a5a76 --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeTruncate_FileAccessRead.cs @@ -0,0 +1,59 @@ +#if FEATURE_TAP +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Renci.SshNet.Sftp; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_OpenAsync_FileModeTruncate_FileAccessRead : SftpFileStreamAsyncTestBase + { + private Random _random; + private string _path; + private FileMode _fileMode; + private FileAccess _fileAccess; + private int _bufferSize; + private ArgumentException _actualException; + + protected override void SetupData() + { + base.SetupData(); + + _random = new Random(); + _path = _random.Next().ToString(); + _fileMode = FileMode.Truncate; + _fileAccess = FileAccess.Read; + _bufferSize = _random.Next(5, 1000); + } + + protected override void SetupMocks() + { + } + + protected override async Task ActAsync() + { + try + { + await SftpFileStream.OpenAsync(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize, default); + Assert.Fail(); + } + catch (ArgumentException ex) + { + _actualException = ex; + } + } + + [TestMethod] + public void CtorShouldHaveThrownArgumentException() + { + Assert.IsNotNull(_actualException); + Assert.IsNull(_actualException.InnerException); + Assert.AreEqual(string.Format("Combining {0}: {1} with {2}: {3} is invalid.", typeof(FileMode).Name, _fileMode, typeof(FileAccess).Name, _fileAccess), _actualException.Message); + Assert.IsNull(_actualException.ParamName); + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeTruncate_FileAccessReadWrite.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeTruncate_FileAccessReadWrite.cs new file mode 100644 index 000000000..2d0efd24f --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeTruncate_FileAccessReadWrite.cs @@ -0,0 +1,136 @@ +#if FEATURE_TAP +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Common; +using Renci.SshNet.Sftp; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_OpenAsync_FileModeTruncate_FileAccessReadWrite : SftpFileStreamAsyncTestBase + { + private Random _random; + private string _path; + private FileMode _fileMode; + private FileAccess _fileAccess; + private int _bufferSize; + private uint _readBufferSize; + private uint _writeBufferSize; + private byte[] _handle; + private SftpFileStream _target; + private CancellationToken _cancellationToken; + + protected override void SetupData() + { + base.SetupData(); + + _random = new Random(); + _path = _random.Next().ToString(); + _fileMode = FileMode.Truncate; + _fileAccess = FileAccess.ReadWrite; + _bufferSize = _random.Next(5, 1000); + _readBufferSize = (uint) _random.Next(5, 1000); + _writeBufferSize = (uint) _random.Next(5, 1000); + _handle = GenerateRandom(_random.Next(1, 10), _random); + _cancellationToken = new CancellationToken(); + } + + protected override void SetupMocks() + { + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestOpenAsync(_path, Flags.Read | Flags.Write | Flags.Truncate, _cancellationToken)) + .ReturnsAsync(_handle); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalReadLength((uint) _bufferSize)) + .Returns(_readBufferSize); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalWriteLength((uint) _bufferSize, _handle)) + .Returns(_writeBufferSize); + } + + protected override async Task ActAsync() + { + _target = await SftpFileStream.OpenAsync(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize, _cancellationToken); + } + + [TestMethod] + public void CanReadShouldReturnTrue() + { + Assert.IsTrue(_target.CanRead); + } + + [TestMethod] + public void CanSeekShouldReturnTrue() + { + Assert.IsTrue(_target.CanSeek); + } + + [TestMethod] + public void CanWriteShouldReturnTrue() + { + Assert.IsTrue(_target.CanWrite); + } + + [TestMethod] + public void CanTimeoutShouldReturnTrue() + { + Assert.IsTrue(_target.CanTimeout); + } + + [TestMethod] + public void PositionShouldReturnZero() + { + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + var actual = _target.Position; + + Assert.AreEqual(0L, actual); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + } + + [TestMethod] + public async Task ReadShouldStartReadingAtBeginningOfFile() + { + var buffer = new byte[8]; + var data = new byte[] { 5, 4, 3, 2, 1 }; + var expected = new byte[] { 0, 5, 4, 3, 2, 1, 0, 0 }; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence).Setup(p => p.RequestReadAsync(_handle, 0UL, _readBufferSize, _cancellationToken)).ReturnsAsync(data); + + var actual = await _target.ReadAsync(buffer, 1, data.Length); + + Assert.AreEqual(data.Length, actual); + Assert.IsTrue(buffer.IsEqualTo(expected)); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + SftpSessionMock.Verify(p => p.RequestReadAsync(_handle, 0UL, _readBufferSize, _cancellationToken), Times.Once); + } + + [TestMethod] + public async Task WriteShouldStartWritingAtBeginningOfFile() + { + var buffer = new byte[_writeBufferSize]; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence).Setup(p => p.RequestWriteAsync(_handle, 0UL, buffer, 0, buffer.Length, _cancellationToken)).Returns(Task.CompletedTask); + + await _target.WriteAsync(buffer, 0, buffer.Length); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + SftpSessionMock.Verify(p => p.RequestWriteAsync(_handle, 0UL, buffer, 0, buffer.Length, _cancellationToken), Times.Once); + } + + [TestMethod] + public void RequestOpenOnSftpSessionShouldBeInvokedOnce() + { + SftpSessionMock.Verify(p => p.RequestOpenAsync(_path, Flags.Read | Flags.Write | Flags.Truncate, _cancellationToken), Times.Once); + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeTruncate_FileAccessWrite.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeTruncate_FileAccessWrite.cs new file mode 100644 index 000000000..5f61e1984 --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeTruncate_FileAccessWrite.cs @@ -0,0 +1,136 @@ +#if FEATURE_TAP +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Sftp; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_OpenAsync_FileModeTruncate_FileAccessWrite : SftpFileStreamAsyncTestBase + { + private Random _random; + private string _path; + private FileMode _fileMode; + private FileAccess _fileAccess; + private int _bufferSize; + private uint _readBufferSize; + private uint _writeBufferSize; + private byte[] _handle; + private SftpFileStream _target; + private CancellationToken _cancellationToken; + + protected override void SetupData() + { + base.SetupData(); + + _random = new Random(); + _path = _random.Next().ToString(); + _fileMode = FileMode.Truncate; + _fileAccess = FileAccess.Write; + _bufferSize = _random.Next(5, 1000); + _readBufferSize = (uint) _random.Next(5, 1000); + _writeBufferSize = (uint) _random.Next(5, 1000); + _handle = GenerateRandom(_random.Next(1, 10), _random); + _cancellationToken = new CancellationToken(); + } + + protected override void SetupMocks() + { + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestOpenAsync(_path, Flags.Write | Flags.Truncate, _cancellationToken)) + .ReturnsAsync(_handle); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalReadLength((uint) _bufferSize)) + .Returns(_readBufferSize); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalWriteLength((uint) _bufferSize, _handle)) + .Returns(_writeBufferSize); + } + + protected override async Task ActAsync() + { + _target = await SftpFileStream.OpenAsync(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize, _cancellationToken); + } + + [TestMethod] + public void CanReadShouldReturnFalse() + { + Assert.IsFalse(_target.CanRead); + } + + [TestMethod] + public void CanSeekShouldReturnTrue() + { + Assert.IsTrue(_target.CanSeek); + } + + [TestMethod] + public void CanWriteShouldReturnTrue() + { + Assert.IsTrue(_target.CanWrite); + } + + [TestMethod] + public void CanTimeoutShouldReturnTrue() + { + Assert.IsTrue(_target.CanTimeout); + } + + [TestMethod] + public void PositionShouldReturnZero() + { + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + var actual = _target.Position; + + Assert.AreEqual(0L, actual); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + } + + [TestMethod] + public async Task ReadShouldThrowNotSupportedException() + { + var buffer = new byte[_readBufferSize]; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + try + { + await _target.ReadAsync(buffer, 0, buffer.Length); + Assert.Fail(); + } + catch (NotSupportedException ex) + { + Assert.IsNull(ex.InnerException); + } + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + } + + [TestMethod] + public async Task WriteShouldStartWritingAtBeginningOfFile() + { + var buffer = new byte[_writeBufferSize]; + + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence).Setup(p => p.RequestWriteAsync(_handle, 0UL, buffer, 0, buffer.Length, _cancellationToken)).Returns(Task.CompletedTask); + + await _target.WriteAsync(buffer, 0, buffer.Length); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); + SftpSessionMock.Verify(p => p.RequestWriteAsync(_handle, 0UL, buffer, 0, buffer.Length, _cancellationToken), Times.Once); + } + + [TestMethod] + public void RequestOpenOnSftpSessionShouldBeInvokedOnce() + { + SftpSessionMock.Verify(p => p.RequestOpenAsync(_path, Flags.Write | Flags.Truncate, _cancellationToken), Times.Once); + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_ReadAsync_ReadMode_NoDataInReaderBufferAndReadLessBytesFromServerThanCountAndEqualToBufferSize.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_ReadAsync_ReadMode_NoDataInReaderBufferAndReadLessBytesFromServerThanCountAndEqualToBufferSize.cs new file mode 100644 index 000000000..13f3e1255 --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_ReadAsync_ReadMode_NoDataInReaderBufferAndReadLessBytesFromServerThanCountAndEqualToBufferSize.cs @@ -0,0 +1,159 @@ +#if FEATURE_TAP +using System; +using System.IO; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Common; +using Renci.SshNet.Sftp; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_ReadAsync_ReadMode_NoDataInReaderBufferAndReadLessBytesFromServerThanCountAndEqualToBufferSize : SftpFileStreamAsyncTestBase + { + private string _path; + private SftpFileStream _target; + private byte[] _handle; + private uint _bufferSize; + private uint _readBufferSize; + private uint _writeBufferSize; + private int _actual; + private byte[] _buffer; + private byte[] _serverData1; + private byte[] _serverData2; + private int _serverData1Length; + private int _serverData2Length; + private int _numberOfBytesToRead; + + protected override void SetupData() + { + base.SetupData(); + + var random = new Random(); + _path = random.Next().ToString(); + _handle = GenerateRandom(5, random); + _bufferSize = (uint)random.Next(1, 1000); + _readBufferSize = 20; + _writeBufferSize = 500; + + _numberOfBytesToRead = (int) _readBufferSize + 5; // greather than read buffer size + _buffer = new byte[_numberOfBytesToRead]; + _serverData1Length = (int) _readBufferSize; // equal to read buffer size + _serverData1 = GenerateRandom(_serverData1Length, random); + _serverData2Length = (int) _readBufferSize; // equal to read buffer size + _serverData2 = GenerateRandom(_serverData2Length, random); + + Assert.IsTrue(_serverData1Length < _numberOfBytesToRead && _serverData1Length == _readBufferSize); + } + + protected override void SetupMocks() + { + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestOpenAsync(_path, Flags.Read, default)) + .ReturnsAsync(_handle); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalReadLength(_bufferSize)) + .Returns(_readBufferSize); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalWriteLength(_bufferSize, _handle)) + .Returns(_writeBufferSize); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.IsOpen) + .Returns(true); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestReadAsync(_handle, 0UL, _readBufferSize, default)) + .ReturnsAsync(_serverData1); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestReadAsync(_handle, (ulong)_serverData1.Length, _readBufferSize, default)) + .ReturnsAsync(_serverData2); + } + + [TestCleanup] + public void TearDown() + { + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestClose(_handle)); + } + + protected override async Task ArrangeAsync() + { + await base.ArrangeAsync(); + + _target = await SftpFileStream.OpenAsync(SftpSessionMock.Object, + _path, + FileMode.Open, + FileAccess.Read, + (int)_bufferSize, + default); + } + + protected override async Task ActAsync() + { + _actual = await _target.ReadAsync(_buffer, 0, _numberOfBytesToRead, default); + } + + [TestMethod] + public void ReadShouldHaveReturnedTheNumberOfBytesRequested() + { + Assert.AreEqual(_numberOfBytesToRead, _actual); + } + + [TestMethod] + public void ReadShouldHaveWrittenBytesToTheCallerSuppliedBuffer() + { + Assert.IsTrue(_serverData1.IsEqualTo(_buffer.Take(_serverData1Length))); + + var bytesWrittenFromSecondRead = _numberOfBytesToRead - _serverData1Length; + Assert.IsTrue(_serverData2.Take(bytesWrittenFromSecondRead).IsEqualTo(_buffer.Take(_serverData1Length, bytesWrittenFromSecondRead))); + } + + [TestMethod] + public void PositionShouldReturnNumberOfBytesWrittenToCallerProvidedBuffer() + { + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + Assert.AreEqual(_actual, _target.Position); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(2)); + } + + [TestMethod] + public async Task ReadShouldReturnAllRemaningBytesFromReadBufferWhenCountIsEqualToNumberOfRemainingBytes() + { + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + var numberOfBytesRemainingInReadBuffer = _serverData1Length + _serverData2Length - _numberOfBytesToRead; + + _buffer = new byte[numberOfBytesRemainingInReadBuffer]; + + var actual = await _target.ReadAsync(_buffer, 0, _buffer.Length); + + Assert.AreEqual(_buffer.Length, actual); + Assert.IsTrue(_serverData2.Take(_numberOfBytesToRead - _serverData1Length, _buffer.Length).IsEqualTo(_buffer)); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(2)); + } + + [TestMethod] + public async Task ReadShouldReturnAllRemaningBytesFromReadBufferAndReadAgainWhenCountIsGreaterThanNumberOfRemainingBytesAndNewReadReturnsZeroBytes() + { + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence).Setup(p => p.RequestReadAsync(_handle, (ulong)(_serverData1Length + _serverData2Length), _readBufferSize, default)).ReturnsAsync(Array.Empty); + + var numberOfBytesRemainingInReadBuffer = _serverData1Length + _serverData2Length - _numberOfBytesToRead; + + _buffer = new byte[numberOfBytesRemainingInReadBuffer + 1]; + + var actual = await _target.ReadAsync(_buffer, 0, _buffer.Length); + + Assert.AreEqual(numberOfBytesRemainingInReadBuffer, actual); + Assert.IsTrue(_serverData2.Take(_numberOfBytesToRead - _serverData1Length, numberOfBytesRemainingInReadBuffer).IsEqualTo(_buffer.Take(numberOfBytesRemainingInReadBuffer))); + Assert.AreEqual(0, _buffer[numberOfBytesRemainingInReadBuffer]); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(2)); + SftpSessionMock.Verify(p => p.RequestReadAsync(_handle, (ulong)(_serverData1Length + _serverData2Length), _readBufferSize, default)); + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_ReadAsync_ReadMode_NoDataInReaderBufferAndReadLessBytesFromServerThanCountAndLessThanBufferSize.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_ReadAsync_ReadMode_NoDataInReaderBufferAndReadLessBytesFromServerThanCountAndLessThanBufferSize.cs new file mode 100644 index 000000000..2da0a4385 --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_ReadAsync_ReadMode_NoDataInReaderBufferAndReadLessBytesFromServerThanCountAndLessThanBufferSize.cs @@ -0,0 +1,152 @@ +#if FEATURE_TAP +using System; +using System.IO; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Common; +using Renci.SshNet.Sftp; +using Renci.SshNet.Tests.Common; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_ReadAsync_ReadMode_NoDataInReaderBufferAndReadLessBytesFromServerThanCountAndLessThanBufferSize : SftpFileStreamAsyncTestBase + { + private string _path; + private SftpFileStream _target; + private byte[] _handle; + private uint _bufferSize; + private uint _readBufferSize; + private uint _writeBufferSize; + private int _actual; + private byte[] _buffer; + private byte[] _serverData; + private int _serverDataLength; + private int _numberOfBytesToRead; + private byte[] _originalBuffer; + + protected override void SetupData() + { + base.SetupData(); + + var random = new Random(); + _path = random.Next().ToString(); + _handle = GenerateRandom(5, random); + _bufferSize = (uint)random.Next(1, 1000); + _readBufferSize = 20; + _writeBufferSize = 500; + + _numberOfBytesToRead = (int) _readBufferSize + 2; // greater than read buffer size + _originalBuffer = GenerateRandom(_numberOfBytesToRead, random); + _buffer = _originalBuffer.Copy(); + + _serverDataLength = (int) _readBufferSize - 1; // less than read buffer size + _serverData = GenerateRandom(_serverDataLength, random); + + Assert.IsTrue(_serverDataLength < _numberOfBytesToRead && _serverDataLength < _readBufferSize); + } + + protected override void SetupMocks() + { + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestOpenAsync(_path, Flags.Read, default)) + .ReturnsAsync(_handle); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalReadLength(_bufferSize)) + .Returns(_readBufferSize); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalWriteLength(_bufferSize, _handle)) + .Returns(_writeBufferSize); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.IsOpen) + .Returns(true); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestReadAsync(_handle, 0UL, _readBufferSize, default)) + .ReturnsAsync(_serverData); + } + + [TestCleanup] + public void TearDown() + { + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestClose(_handle)); + } + + protected override async Task ArrangeAsync() + { + await base.ArrangeAsync(); + + _target = await SftpFileStream.OpenAsync(SftpSessionMock.Object, + _path, + FileMode.Open, + FileAccess.Read, + (int)_bufferSize, + default); + } + + protected override async Task ActAsync() + { + _actual = await _target.ReadAsync(_buffer, 0, _numberOfBytesToRead, default); + } + + [TestMethod] + public void ReadShouldHaveReturnedTheNumberOfBytesReturnedByTheReadFromTheServer() + { + Assert.AreEqual(_serverDataLength, _actual); + } + + [TestMethod] + public void ReadShouldHaveWrittenBytesToTheCallerSuppliedBufferAndRemainingBytesShouldRemainUntouched() + { + Assert.IsTrue(_serverData.IsEqualTo(_buffer.Take(_serverDataLength))); + Assert.IsTrue(_originalBuffer.Take(_serverDataLength, _originalBuffer.Length - _serverDataLength).IsEqualTo(_buffer.Take(_serverDataLength, _buffer.Length - _serverDataLength))); + } + + [TestMethod] + public void PositionShouldReturnNumberOfBytesWrittenToCallerProvidedBuffer() + { + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + Assert.AreEqual(_actual, _target.Position); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(2)); + } + + [TestMethod] + public async Task SubsequentReadShouldReadAgainFromCurrentPositionFromServerAndReturnZeroWhenServerReturnsZeroBytes() + { + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestReadAsync(_handle, (ulong) _actual, _readBufferSize, default)) + .ReturnsAsync(Array.Empty); + + var buffer = _originalBuffer.Copy(); + var actual = await _target.ReadAsync(buffer, 0, buffer.Length); + + Assert.AreEqual(0, actual); + Assert.IsTrue(_originalBuffer.IsEqualTo(buffer)); + + SftpSessionMock.Verify(p => p.RequestReadAsync(_handle, (ulong)_actual, _readBufferSize, default), Times.Once); + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(2)); + } + + [TestMethod] + public async Task SubsequentReadShouldReadAgainFromCurrentPositionFromServerAndNotUpdatePositionWhenServerReturnsZeroBytes() + { + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestReadAsync(_handle, (ulong)_actual, _readBufferSize, default)) + .ReturnsAsync(Array.Empty); + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + await _target.ReadAsync(new byte[10], 0, 10); + + Assert.AreEqual(_actual, _target.Position); + + SftpSessionMock.Verify(p => p.RequestReadAsync(_handle, (ulong)_actual, _readBufferSize, default), Times.Once); + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(3)); + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_ReadAsync_ReadMode_NoDataInReaderBufferAndReadMoreBytesFromServerThanCount.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_ReadAsync_ReadMode_NoDataInReaderBufferAndReadMoreBytesFromServerThanCount.cs new file mode 100644 index 000000000..80895217e --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_ReadAsync_ReadMode_NoDataInReaderBufferAndReadMoreBytesFromServerThanCount.cs @@ -0,0 +1,143 @@ +#if FEATURE_TAP +using System; +using System.IO; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Sftp; +using Renci.SshNet.Common; +using System.Threading.Tasks; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_ReadAsync_ReadMode_NoDataInReaderBufferAndReadMoreBytesFromServerThanCount : SftpFileStreamAsyncTestBase + { + private string _path; + private SftpFileStream _target; + private byte[] _handle; + private uint _bufferSize; + private uint _readBufferSize; + private uint _writeBufferSize; + private int _actual; + private byte[] _buffer; + private byte[] _serverData; + private int _numberOfBytesToWriteToReadBuffer; + private int _numberOfBytesToRead; + + protected override void SetupData() + { + base.SetupData(); + + var random = new Random(); + _path = random.Next().ToString(); + _handle = GenerateRandom(5, random); + _bufferSize = (uint) random.Next(1, 1000); + _readBufferSize = 20; + _writeBufferSize = 500; + + _numberOfBytesToRead = 20; + _buffer = new byte[_numberOfBytesToRead]; + _numberOfBytesToWriteToReadBuffer = 10; // should be less than _readBufferSize + _serverData = GenerateRandom(_numberOfBytesToRead + _numberOfBytesToWriteToReadBuffer, random); + } + + protected override void SetupMocks() + { + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestOpenAsync(_path, Flags.Read, default)) + .ReturnsAsync(_handle); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalReadLength(_bufferSize)) + .Returns(_readBufferSize); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalWriteLength(_bufferSize, _handle)) + .Returns(_writeBufferSize); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.IsOpen) + .Returns(true); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestReadAsync(_handle, 0UL, _readBufferSize, default)) + .ReturnsAsync(_serverData); + } + + [TestCleanup] + public void TearDown() + { + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestClose(_handle)); + } + + protected override async Task ArrangeAsync() + { + await base.ArrangeAsync(); + + _target = await SftpFileStream.OpenAsync(SftpSessionMock.Object, + _path, + FileMode.Open, + FileAccess.Read, + (int)_bufferSize, + default); + } + + protected override async Task ActAsync() + { + _actual = await _target.ReadAsync(_buffer, 0, _numberOfBytesToRead, default); + } + + [TestMethod] + public void ReadShouldHaveReturnedTheNumberOfBytesWrittenToCallerSuppliedBuffer() + { + Assert.AreEqual(_numberOfBytesToRead, _actual); + } + + [TestMethod] + public void ReadShouldHaveWrittenBytesToTheCallerSuppliedBuffer() + { + Assert.IsTrue(_serverData.Take(_actual).IsEqualTo(_buffer)); + } + + [TestMethod] + public void PositionShouldReturnNumberOfBytesWrittenToCallerProvidedBuffer() + { + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + Assert.AreEqual(_actual, _target.Position); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(2)); + } + + [TestMethod] + public async Task SubsequentReadShouldReturnAllRemaningBytesFromReadBufferWhenCountIsEqualToNumberOfRemainingBytes() + { + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + var buffer = new byte[_numberOfBytesToWriteToReadBuffer]; + + var actual = await _target.ReadAsync(buffer, 0, _numberOfBytesToWriteToReadBuffer, default); + + Assert.AreEqual(_numberOfBytesToWriteToReadBuffer, actual); + Assert.IsTrue(_serverData.Take(_numberOfBytesToRead, _numberOfBytesToWriteToReadBuffer).IsEqualTo(buffer)); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(2)); + } + + [TestMethod] + public async Task SubsequentReadShouldReturnAllRemaningBytesFromReadBufferAndReadAgainWhenCountIsGreaterThanNumberOfRemainingBytesAndNewReadReturnsZeroBytes() + { + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence).Setup(p => p.RequestReadAsync(_handle, (ulong)(_serverData.Length), _readBufferSize, default)).ReturnsAsync(Array.Empty); + + var buffer = new byte[_numberOfBytesToWriteToReadBuffer + 1]; + + var actual = await _target.ReadAsync(buffer, 0, buffer.Length); + + Assert.AreEqual(_numberOfBytesToWriteToReadBuffer, actual); + Assert.IsTrue(_serverData.Take(_numberOfBytesToRead, _numberOfBytesToWriteToReadBuffer).IsEqualTo(buffer.Take(_numberOfBytesToWriteToReadBuffer))); + Assert.AreEqual(0, buffer[_numberOfBytesToWriteToReadBuffer]); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(2)); + SftpSessionMock.Verify(p => p.RequestReadAsync(_handle, (ulong)(_serverData.Length), _readBufferSize, default)); + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_WriteAsync_SessionOpen_CountGreatherThanTwoTimesTheWriteBufferSize.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_WriteAsync_SessionOpen_CountGreatherThanTwoTimesTheWriteBufferSize.cs new file mode 100644 index 000000000..dcbfedf63 --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_WriteAsync_SessionOpen_CountGreatherThanTwoTimesTheWriteBufferSize.cs @@ -0,0 +1,143 @@ +#if FEATURE_TAP +using System; +using System.Globalization; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Common; +using Renci.SshNet.Sftp; +using Renci.SshNet.Sftp.Responses; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_WriteAsync_SessionOpen_CountGreatherThanTwoTimesTheWriteBufferSize : SftpFileStreamAsyncTestBase + { + private SftpFileStream _target; + private string _path; + private byte[] _handle; + private uint _bufferSize; + private uint _readBufferSize; + private uint _writeBufferSize; + private byte[] _data; + private int _count; + private int _offset; + private Random _random; + private uint _expectedWrittenByteCount; + private int _expectedBufferedByteCount; + private byte[] _expectedBufferedBytes; + private CancellationToken _cancellationToken; + + protected override void SetupData() + { + base.SetupData(); + + _random = new Random(); + _path = _random.Next().ToString(CultureInfo.InvariantCulture); + _handle = GenerateRandom(5, _random); + _bufferSize = (uint)_random.Next(1, 1000); + _readBufferSize = (uint) _random.Next(0, 1000); + _writeBufferSize = (uint) _random.Next(500, 1000); + _data = new byte[(_writeBufferSize * 2) + 15]; + _random.NextBytes(_data); + _offset = _random.Next(1, 5); + // to get multiple SSH_FXP_WRITE messages (and verify the offset is updated correctly), we make sure + // the number of bytes to write is at least two times the write buffer size; we write a few extra bytes to + // ensure the buffer is not empty after the writes so we can verify whether Length, Dispose and Flush + // flush the buffer + _count = ((int) _writeBufferSize * 2) + _random.Next(1, 5); + + _expectedWrittenByteCount = (2 * _writeBufferSize); + _expectedBufferedByteCount = (int)(_count - _expectedWrittenByteCount); + _expectedBufferedBytes = _data.Take(_offset + (int)_expectedWrittenByteCount, _expectedBufferedByteCount); + _cancellationToken = new CancellationToken(); + } + + protected override void SetupMocks() + { + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestOpenAsync(_path, Flags.Write | Flags.CreateNewOrOpen | Flags.Truncate, _cancellationToken)) + .ReturnsAsync(_handle); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalReadLength(_bufferSize)) + .Returns(_readBufferSize); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.CalculateOptimalWriteLength(_bufferSize, _handle)) + .Returns(_writeBufferSize); + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestWriteAsync(_handle, 0, _data, _offset, (int)_writeBufferSize, _cancellationToken)) + .Returns(Task.CompletedTask); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestWriteAsync(_handle, _writeBufferSize, _data, _offset + (int)_writeBufferSize, (int)_writeBufferSize, _cancellationToken)) + .Returns(Task.CompletedTask); + } + + [TestCleanup] + public void TearDown() + { + if (SftpSessionMock != null) + { + // allow Dispose to complete successfully + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.IsOpen) + .Returns(true); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestWriteAsync(_handle, _expectedWrittenByteCount, It.IsAny(), 0, _expectedBufferedByteCount, _cancellationToken)) + .Returns(Task.CompletedTask); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestClose(_handle)); + } + } + + protected override async Task ArrangeAsync() + { + await base.ArrangeAsync(); + + _target = await SftpFileStream.OpenAsync(SftpSessionMock.Object, _path, FileMode.Create, FileAccess.Write, (int) _bufferSize, _cancellationToken); + } + + protected override Task ActAsync() + { + return _target.WriteAsync(_data, _offset, _count); + } + + [TestMethod] + public void RequestWriteOnSftpSessionShouldBeInvokedTwice() + { + SftpSessionMock.Verify(p => p.RequestWriteAsync(_handle, 0, _data, _offset, (int)_writeBufferSize, _cancellationToken), Times.Once); + SftpSessionMock.Verify(p => p.RequestWriteAsync(_handle, _writeBufferSize, _data, _offset + (int)_writeBufferSize, (int)_writeBufferSize, _cancellationToken), Times.Once); + } + + [TestMethod] + public void PositionShouldBeNumberOfBytesWrittenToFileAndNUmberOfBytesInBuffer() + { + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + Assert.AreEqual(_count, _target.Position); + } + + [TestMethod] + public async Task FlushShouldFlushBuffer() + { + byte[] actualFlushedData = null; + + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.IsOpen) + .Returns(true); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestWriteAsync(_handle, _expectedWrittenByteCount, It.IsAny(), 0, _expectedBufferedByteCount, _cancellationToken)) + .Callback((handle, serverFileOffset, data, offset, length, ct) => actualFlushedData = data.Take(offset, length)) + .Returns(Task.CompletedTask); + + await _target.FlushAsync(); + + Assert.IsTrue(actualFlushedData.IsEqualTo(_expectedBufferedBytes)); + + SftpSessionMock.Verify(p => p.RequestWriteAsync(_handle, _expectedWrittenByteCount, It.IsAny(), 0, _expectedBufferedByteCount, _cancellationToken), Times.Once); + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/SftpClientTest.ConnectAsync.cs b/src/Renci.SshNet.Tests/Classes/SftpClientTest.ConnectAsync.cs new file mode 100644 index 000000000..75602ea2c --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/SftpClientTest.ConnectAsync.cs @@ -0,0 +1,48 @@ +#if FEATURE_TAP +using System; +using System.Net.Sockets; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Renci.SshNet.Tests.Classes +{ + public partial class SftpClientTest + { + [TestMethod] + public async Task ConnectAsync_HostNameInvalid_ShouldThrowSocketExceptionWithErrorCodeHostNotFound() + { + var connectionInfo = new ConnectionInfo(Guid.NewGuid().ToString("N"), 40, "user", + new KeyboardInteractiveAuthenticationMethod("user")); + var sftpClient = new SftpClient(connectionInfo); + + try + { + await sftpClient.ConnectAsync(default); + Assert.Fail(); + } + catch (SocketException ex) + { + Assert.AreEqual(SocketError.HostNotFound, ex.SocketErrorCode); + } + } + + [TestMethod] + public async Task ConnectAsync_ProxyHostNameInvalid_ShouldThrowSocketExceptionWithErrorCodeHostNotFound() + { + var connectionInfo = new ConnectionInfo("localhost", 40, "user", ProxyTypes.Http, Guid.NewGuid().ToString("N"), 80, + "proxyUser", "proxyPwd", new KeyboardInteractiveAuthenticationMethod("user")); + var sftpClient = new SftpClient(connectionInfo); + + try + { + await sftpClient.ConnectAsync(default); + Assert.Fail(); + } + catch (SocketException ex) + { + Assert.AreEqual(SocketError.HostNotFound, ex.SocketErrorCode); + } + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/SftpClientTest.DeleteFileAsync.cs b/src/Renci.SshNet.Tests/Classes/SftpClientTest.DeleteFileAsync.cs new file mode 100644 index 000000000..20e68e812 --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/SftpClientTest.DeleteFileAsync.cs @@ -0,0 +1,27 @@ +#if FEATURE_TAP +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Renci.SshNet.Tests.Properties; +using System; +using System.Threading.Tasks; + +namespace Renci.SshNet.Tests.Classes +{ + /// + /// Implementation of the SSH File Transfer Protocol (SFTP) over SSH. + /// + public partial class SftpClientTest + { + [TestMethod] + [TestCategory("Sftp")] + [Description("Test passing null to DeleteFile.")] + [ExpectedException(typeof(ArgumentException))] + public async Task Test_Sftp_DeleteFileAsync_Null() + { + using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD)) + { + await sftp.DeleteFileAsync(null, default); + } + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/SftpClientTest.RenameFileAsync.cs b/src/Renci.SshNet.Tests/Classes/SftpClientTest.RenameFileAsync.cs new file mode 100644 index 000000000..38d651f97 --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/SftpClientTest.RenameFileAsync.cs @@ -0,0 +1,66 @@ +#if FEATURE_TAP +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Renci.SshNet.Tests.Properties; +using System; +using System.IO; +using System.Threading.Tasks; + +namespace Renci.SshNet.Tests.Classes +{ + /// + /// Implementation of the SSH File Transfer Protocol (SFTP) over SSH. + /// + public partial class SftpClientTest + { + [TestMethod] + [TestCategory("Sftp")] + [TestCategory("integration")] + public async Task Test_Sftp_RenameFileAsync() + { + using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD)) + { + await sftp.ConnectAsync(default); + + string uploadedFileName = Path.GetTempFileName(); + string remoteFileName1 = Path.GetRandomFileName(); + string remoteFileName2 = Path.GetRandomFileName(); + + this.CreateTestFile(uploadedFileName, 1); + + using (var file = File.OpenRead(uploadedFileName)) + { + using (Stream remoteStream = await sftp.OpenAsync(remoteFileName1, FileMode.CreateNew, FileAccess.Write, default)) + { + await file.CopyToAsync(remoteStream, 81920, default); + } + } + + await sftp.RenameFileAsync(remoteFileName1, remoteFileName2, default); + + File.Delete(uploadedFileName); + + sftp.Disconnect(); + } + + RemoveAllFiles(); + } + + [TestMethod] + [TestCategory("Sftp")] + [TestCategory("integration")] + [Description("Test passing null to RenameFile.")] + [ExpectedException(typeof(ArgumentNullException))] + public async Task Test_Sftp_RenameFileAsync_Null() + { + using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD)) + { + await sftp.ConnectAsync(default); + + await sftp.RenameFileAsync(null, null, default); + + sftp.Disconnect(); + } + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/SftpClientTest.cs b/src/Renci.SshNet.Tests/Classes/SftpClientTest.cs index 8f84546bf..506891910 100644 --- a/src/Renci.SshNet.Tests/Classes/SftpClientTest.cs +++ b/src/Renci.SshNet.Tests/Classes/SftpClientTest.cs @@ -94,7 +94,11 @@ public void OperationTimeout_LessThanLowerLimit() catch (ArgumentOutOfRangeException ex) { Assert.IsNull(ex.InnerException); +#if NETFRAMEWORK Assert.AreEqual("The timeout must represent a value between -1 and Int32.MaxValue, inclusive." + Environment.NewLine + "Parameter name: " + ex.ParamName, ex.Message); +#else + Assert.AreEqual("The timeout must represent a value between -1 and Int32.MaxValue, inclusive. (Parameter '" + ex.ParamName + "')", ex.Message); +#endif Assert.AreEqual("value", ex.ParamName); } } @@ -113,7 +117,11 @@ public void OperationTimeout_GreaterThanLowerLimit() catch (ArgumentOutOfRangeException ex) { Assert.IsNull(ex.InnerException); +#if NETFRAMEWORK Assert.AreEqual("The timeout must represent a value between -1 and Int32.MaxValue, inclusive." + Environment.NewLine + "Parameter name: " + ex.ParamName, ex.Message); +#else + Assert.AreEqual("The timeout must represent a value between -1 and Int32.MaxValue, inclusive. (Parameter '" + ex.ParamName + "')", ex.Message); +#endif Assert.AreEqual("value", ex.ParamName); } } diff --git a/src/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj b/src/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj index 8ba9f3077..3b38bfbe8 100644 --- a/src/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj +++ b/src/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj @@ -1,14 +1,18 @@  - true + 7.3 + true ..\Renci.SshNet.snk - net35;net40;netcoreapp2.1;netcoreapp2.2 + net35;net472;netcoreapp2.1 - net35;net40;netcoreapp2.1;netcoreapp2.2;netcoreapp3.0 + net35;net472;netcoreapp3.1;net5.0 + + + net472;netcoreapp3.1;net5.0;net6.0 @@ -17,14 +21,23 @@ FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_TPL + + FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_TPL;FEATURE_TAP + - FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_TPL + FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_TPL;FEATURE_TAP - FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_TPL + FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_TPL;FEATURE_TAP - - FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_TPL + + FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_TPL;FEATURE_TAP + + + FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_TPL;FEATURE_TAP + + + FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_TPL;FEATURE_TAP @@ -93,35 +106,11 @@ - - - $(MSTestV1UnitTestFrameworkAssembly) - - - - - - - - 2.1.0 - - - - - - - - 2.1.0 - - - - - - - - 2.1.0 - - + + + + +