diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Ctor_FileModeAppend_FileAccessRead.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Ctor_FileModeAppend_FileAccessRead.cs index 4da49ac7..09423c6b 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Ctor_FileModeAppend_FileAccessRead.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Ctor_FileModeAppend_FileAccessRead.cs @@ -48,7 +48,7 @@ namespace Renci.SshNet.Tests.Classes.Sftp { 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.AreEqual(string.Format("{0} mode can be requested only when combined with write-only access.", _fileMode), _actualException.Message); Assert.IsNull(_actualException.ParamName); } } diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Ctor_FileModeAppend_FileAccessReadWrite.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Ctor_FileModeAppend_FileAccessReadWrite.cs index 4af2e540..8f31995c 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Ctor_FileModeAppend_FileAccessReadWrite.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Ctor_FileModeAppend_FileAccessReadWrite.cs @@ -1,10 +1,7 @@ using System; using System.IO; -using System.Threading; using Microsoft.VisualStudio.TestTools.UnitTesting; -using Moq; using Renci.SshNet.Sftp; -using Renci.SshNet.Tests.Common; namespace Renci.SshNet.Tests.Classes.Sftp { @@ -16,11 +13,7 @@ namespace Renci.SshNet.Tests.Classes.Sftp 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 ArgumentException _actualException; protected override void SetupData() { @@ -31,138 +24,32 @@ namespace Renci.SshNet.Tests.Classes.Sftp _fileMode = FileMode.Append; _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); - _fileAttributes = new SftpFileAttributesBuilder().WithLastAccessTime(DateTime.Now.AddSeconds(_random.Next())) - .WithLastWriteTime(DateTime.Now.AddSeconds(_random.Next())) - .WithSize(_random.Next()) - .WithUserId(_random.Next()) - .WithGroupId(_random.Next()) - .WithPermissions((uint)_random.Next()) - .Build(); } protected override void SetupMocks() { - SftpSessionMock.InSequence(MockSequence) - .Setup(p => p.RequestOpen(_path, Flags.Read | Flags.Write | Flags.Append, false)) - .Returns(_handle); - SftpSessionMock.InSequence(MockSequence) - .Setup(p => p.CalculateOptimalReadLength((uint)_bufferSize)) - .Returns(_readBufferSize); - SftpSessionMock.InSequence(MockSequence) - .Setup(p => p.CalculateOptimalWriteLength((uint)_bufferSize, _handle)) - .Returns(_writeBufferSize); - SftpSessionMock.InSequence(MockSequence) - .Setup(p => p.RequestFStat(_handle, false)) - .Returns(_fileAttributes); } protected override void Act() { - _target = new SftpFileStream(SftpSessionMock.Object, - _path, - _fileMode, - _fileAccess, - _bufferSize); + try + { + new SftpFileStream(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize); + Assert.Fail(); + } + catch (ArgumentException ex) + { + _actualException = ex; + } } [TestMethod] - public void CanReadShouldReturnTrue() + public void CtorShouldHaveThrownArgumentException() { - 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 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 void ReadShouldStartReadingAtEndOfFile() - { - 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.RequestRead(_handle, (ulong)_fileAttributes.Size, _readBufferSize)).Returns(data); - - var actual = _target.Read(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.RequestRead(_handle, (ulong)_fileAttributes.Size, _readBufferSize), Times.Once); - } - - [TestMethod] - public void ReadByteShouldStartReadingAtEndOfFile() - { - var data = GenerateRandom(5, _random); - - SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); - SftpSessionMock.InSequence(MockSequence).Setup(p => p.RequestRead(_handle, (ulong) _fileAttributes.Size, _readBufferSize)).Returns(data); - - var actual = _target.ReadByte(); - - Assert.AreEqual(data[0], actual); - - SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); - SftpSessionMock.Verify(p => p.RequestRead(_handle, (ulong) _fileAttributes.Size, _readBufferSize), Times.Once); - } - - [TestMethod] - public void WriteShouldStartWritingAtEndOfFile() - { - var buffer = new byte[_writeBufferSize]; - - SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); - SftpSessionMock.InSequence(MockSequence).Setup(p => p.RequestWrite(_handle, (ulong) _fileAttributes.Size, buffer, 0, buffer.Length, It.IsNotNull(), null)); - - _target.Write(buffer, 0, buffer.Length); - - SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(1)); - SftpSessionMock.Verify(p => p.RequestWrite(_handle, (ulong) _fileAttributes.Size, buffer, 0, buffer.Length, It.IsNotNull(), null), Times.Once); - } - - [TestMethod] - public void RequestOpenOnSftpSessionShouldBeInvokedOnce() - { - SftpSessionMock.Verify(p => p.RequestOpen(_path, Flags.Read | Flags.Write | Flags.Append, false), Times.Once); - } - - [TestMethod] - public void RequestFStatOnSftpSessionShouldBeInvokedOnce() - { - SftpSessionMock.Verify(p => p.RequestFStat(_handle, false), Times.Once); + 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); } } } diff --git a/src/Renci.SshNet/Sftp/SftpFileStream.cs b/src/Renci.SshNet/Sftp/SftpFileStream.cs index 500e1ba9..bae45745 100644 --- a/src/Renci.SshNet/Sftp/SftpFileStream.cs +++ b/src/Renci.SshNet/Sftp/SftpFileStream.cs @@ -202,6 +202,11 @@ namespace Renci.SshNet.Sftp throw new ArgumentOutOfRangeException("access"); } + if ((access & FileAccess.Read) != 0 && mode == FileMode.Append) + { + throw new ArgumentException(string.Format("{0} mode can be requested only when combined with write-only access.", mode.ToString("G"))); + } + if ((access & FileAccess.Write) == 0) { if (mode == FileMode.Create || mode == FileMode.CreateNew || mode == FileMode.Truncate || mode == FileMode.Append)