From bdcf48b6ad45dfb2772ea9007f549fd97145244b Mon Sep 17 00:00:00 2001 From: LemonPi314 <49930425+LemonPi314@users.noreply.github.com> Date: Tue, 4 Jan 2022 20:43:44 -0500 Subject: [PATCH 1/7] Update .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 7d6bdbf60..357c40337 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,6 @@ project.lock.json # Build outputs build/target/ + +# Visual Studio cache/options directory +.vs/ From a6b5e6e3067746441e00c4f622c90c6a3ebe5ccc Mon Sep 17 00:00:00 2001 From: LemonPi314 <49930425+LemonPi314@users.noreply.github.com> Date: Tue, 4 Jan 2022 20:44:37 -0500 Subject: [PATCH 2/7] Fix offset operations in SftpFileStream.Seek --- src/Renci.SshNet/Sftp/SftpFileStream.cs | 59 ++++++++----------------- 1 file changed, 19 insertions(+), 40 deletions(-) diff --git a/src/Renci.SshNet/Sftp/SftpFileStream.cs b/src/Renci.SshNet/Sftp/SftpFileStream.cs index ecb424567..5df9a4fde 100644 --- a/src/Renci.SshNet/Sftp/SftpFileStream.cs +++ b/src/Renci.SshNet/Sftp/SftpFileStream.cs @@ -788,26 +788,6 @@ public override long Seek(long offset, SeekOrigin origin) { // Flush the write buffer and then seek. FlushWriteBuffer(); - - switch (origin) - { - case SeekOrigin.Begin: - newPosn = offset; - break; - case SeekOrigin.Current: - newPosn = _position + offset; - break; - case SeekOrigin.End: - var attributes = _session.RequestFStat(_handle, false); - newPosn = attributes.Size - offset; - break; - } - - if (newPosn == -1) - { - throw new EndOfStreamException("End of stream."); - } - _position = newPosn; } else { @@ -838,29 +818,28 @@ public override long Seek(long offset, SeekOrigin origin) // Abandon the read buffer. _bufferPosition = 0; _bufferLen = 0; + } - // Seek to the new position. - switch (origin) - { - case SeekOrigin.Begin: - newPosn = offset; - break; - case SeekOrigin.Current: - newPosn = _position + offset; - break; - case SeekOrigin.End: - var attributes = _session.RequestFStat(_handle, false); - newPosn = attributes.Size - offset; - break; - } - - if (newPosn < 0) - { - throw new EndOfStreamException(); - } + // Seek to the new position. + switch (origin) + { + case SeekOrigin.Begin: + newPosn = offset; + break; + case SeekOrigin.Current: + newPosn = _position + offset; + break; + case SeekOrigin.End: + var attributes = _session.RequestFStat(_handle, false); + newPosn = attributes.Size + offset; + break; + } - _position = newPosn; + if (newPosn < 0) + { + throw new EndOfStreamException("End of stream."); } + _position = newPosn; return _position; } } From 161c87e32308712aa56856abb521ed09a7be88d5 Mon Sep 17 00:00:00 2001 From: LemonPi314 <49930425+LemonPi314@users.noreply.github.com> Date: Wed, 16 Feb 2022 18:57:15 -0500 Subject: [PATCH 3/7] Fix seek exception message and add default case for invalid seek origin --- src/Renci.SshNet/Sftp/SftpFileStream.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Renci.SshNet/Sftp/SftpFileStream.cs b/src/Renci.SshNet/Sftp/SftpFileStream.cs index 5df9a4fde..09f7ee1eb 100644 --- a/src/Renci.SshNet/Sftp/SftpFileStream.cs +++ b/src/Renci.SshNet/Sftp/SftpFileStream.cs @@ -833,12 +833,15 @@ public override long Seek(long offset, SeekOrigin origin) var attributes = _session.RequestFStat(_handle, false); newPosn = attributes.Size + offset; break; + default: + throw new ArgumentException("Invalid seek origin.", "origin"); } if (newPosn < 0) { - throw new EndOfStreamException("End of stream."); + throw new EndOfStreamException(); } + _position = newPosn; return _position; } From 731571c2495d759c20bb6970f28a0d0aef0988bb Mon Sep 17 00:00:00 2001 From: LemonPi314 <49930425+LemonPi314@users.noreply.github.com> Date: Thu, 17 Nov 2022 20:45:38 -0500 Subject: [PATCH 4/7] Revert .gitignore changes --- .gitignore | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitignore b/.gitignore index 357c40337..7d6bdbf60 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,3 @@ project.lock.json # Build outputs build/target/ - -# Visual Studio cache/options directory -.vs/ From fcf3c566eba52f17ed15b1d6ec9f564ffafbdd5b Mon Sep 17 00:00:00 2001 From: LemonPi314 <49930425+LemonPi314@users.noreply.github.com> Date: Thu, 17 Nov 2022 23:16:03 -0500 Subject: [PATCH 5/7] Use named params when throwing ArgumentException --- src/Renci.SshNet/Sftp/SftpFileStream.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Renci.SshNet/Sftp/SftpFileStream.cs b/src/Renci.SshNet/Sftp/SftpFileStream.cs index 09f7ee1eb..b47023687 100644 --- a/src/Renci.SshNet/Sftp/SftpFileStream.cs +++ b/src/Renci.SshNet/Sftp/SftpFileStream.cs @@ -834,7 +834,7 @@ public override long Seek(long offset, SeekOrigin origin) newPosn = attributes.Size + offset; break; default: - throw new ArgumentException("Invalid seek origin.", "origin"); + throw new ArgumentException(message: "Invalid seek origin.", paramName: "origin"); } if (newPosn < 0) From 0cf229aa1d7336617e62768bcd9acc3c74da1d4b Mon Sep 17 00:00:00 2001 From: LemonPi314 <49930425+LemonPi314@users.noreply.github.com> Date: Fri, 18 Nov 2022 00:02:37 -0500 Subject: [PATCH 6/7] Add tests for seeking from end of file --- ...ningOfStream_OriginEndAndOffsetNegative.cs | 102 ++++++++++++++++++ ...ningOfStream_OriginEndAndOffsetPositive.cs | 92 ++++++++++++++++ ...eginningOfStream_OriginEndAndOffsetZero.cs | 90 ++++++++++++++++ 3 files changed, 284 insertions(+) create mode 100644 src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetNegative.cs create mode 100644 src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetPositive.cs create mode 100644 src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetZero.cs diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetNegative.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetNegative.cs new file mode 100644 index 000000000..ef9174ad7 --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetNegative.cs @@ -0,0 +1,102 @@ +using System; +using System.IO; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Sftp; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetNegative : SftpFileStreamTestBase + { + 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 int _offset; + private SftpFileAttributes _attributes; + private EndOfStreamException _actualException; + + 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); + _offset = _random.Next(int.MinValue, -1); + _attributes = SftpFileAttributes.Empty; + } + + protected override void SetupMocks() + { + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestOpen(_path, Flags.Read | Flags.CreateNewOrOpen, 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.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestFStat(_handle, false)) + .Returns(_attributes); + } + + protected override void Arrange() + { + base.Arrange(); + + _target = new SftpFileStream(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize); + } + + protected override void Act() + { + try + { + _target.Seek(_offset, SeekOrigin.End); + Assert.Fail(); + } + catch (EndOfStreamException ex) + { + _actualException = ex; + } + } + + [TestMethod] + public void SeekShouldHaveThrownEndOfStreamException() + { + Assert.IsNotNull(_actualException); + Assert.IsNull(_actualException.InnerException); + Assert.AreEqual("Attempted to read past the end of the stream.", _actualException.Message); + } + + [TestMethod] + public void IsOpenOnSftpSessionShouldHaveBeenInvokedOnce() + { + SftpSessionMock.Verify(p => p.IsOpen, Times.Once); + } + + [TestMethod] + public void PositionShouldReturnZero() + { + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + Assert.AreEqual(0L, _target.Position); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(2)); + } + } +} diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetPositive.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetPositive.cs new file mode 100644 index 000000000..76fc6e8c5 --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetPositive.cs @@ -0,0 +1,92 @@ +using System; +using System.IO; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Sftp; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetPositive : SftpFileStreamTestBase + { + 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 int _offset; + private SftpFileAttributes _attributes; + private long _actual; + + 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); + _offset = _random.Next(1, int.MaxValue); + _attributes = SftpFileAttributes.Empty; + } + + protected override void SetupMocks() + { + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestOpen(_path, Flags.Read | Flags.CreateNewOrOpen, 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.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestFStat(_handle, false)) + .Returns(_attributes); + } + + protected override void Arrange() + { + base.Arrange(); + + _target = new SftpFileStream(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize); + } + + protected override void Act() + { + _actual = _target.Seek(_offset, SeekOrigin.End); + } + + [TestMethod] + public void SeekShouldHaveReturnedOffset() + { + Assert.AreEqual(_offset, _actual); + } + + [TestMethod] + public void IsOpenOnSftpSessionShouldHaveBeenInvokedOnce() + { + SftpSessionMock.Verify(p => p.IsOpen, Times.Once); + } + + [TestMethod] + public void PositionShouldReturnOffset() + { + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + Assert.AreEqual(_offset, _target.Position); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(2)); + } + } +} diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetZero.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetZero.cs new file mode 100644 index 000000000..02313b95a --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetZero.cs @@ -0,0 +1,90 @@ +using System; +using System.IO; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Sftp; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetZero : SftpFileStreamTestBase + { + 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 _attributes; + private long _actual; + + 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); + _attributes = SftpFileAttributes.Empty; + } + + protected override void SetupMocks() + { + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestOpen(_path, Flags.Read | Flags.CreateNewOrOpen, 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.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence) + .Setup(p => p.RequestFStat(_handle, false)) + .Returns(_attributes); + } + + protected override void Arrange() + { + base.Arrange(); + + _target = new SftpFileStream(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize); + } + + protected override void Act() + { + _actual = _target.Seek(0L, SeekOrigin.End); + } + + [TestMethod] + public void SeekShouldHaveReturnedZero() + { + Assert.AreEqual(0L, _actual); + } + + [TestMethod] + public void IsOpenOnSftpSessionShouldHaveBeenInvokedOnce() + { + SftpSessionMock.Verify(p => p.IsOpen, Times.Once); + } + + [TestMethod] + public void PositionShouldReturnZero() + { + SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + + Assert.AreEqual(0L, _target.Position); + + SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(2)); + } + } +} From 8d7e0048fd9710ccce466f1193750b8581925cda Mon Sep 17 00:00:00 2001 From: LemonPi314 <49930425+LemonPi314@users.noreply.github.com> Date: Fri, 18 Nov 2022 16:53:03 -0500 Subject: [PATCH 7/7] Fix seek tests --- ...ningOfStream_OriginEndAndOffsetNegative.cs | 55 ++++++++++--------- ...ningOfStream_OriginEndAndOffsetPositive.cs | 35 ++++++++---- ...eginningOfStream_OriginEndAndOffsetZero.cs | 43 ++++++++++----- 3 files changed, 79 insertions(+), 54 deletions(-) diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetNegative.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetNegative.cs index ef9174ad7..e47e716e1 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetNegative.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetNegative.cs @@ -16,11 +16,12 @@ public class SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndO private int _bufferSize; private uint _readBufferSize; private uint _writeBufferSize; + private int _length; private byte[] _handle; private SftpFileStream _target; private int _offset; private SftpFileAttributes _attributes; - private EndOfStreamException _actualException; + private long _actual; protected override void SetupData() { @@ -29,29 +30,38 @@ protected override void SetupData() _random = new Random(); _path = _random.Next().ToString(); _fileMode = FileMode.OpenOrCreate; - _fileAccess = FileAccess.Read; + _fileAccess = FileAccess.Write; _bufferSize = _random.Next(5, 1000); _readBufferSize = (uint)_random.Next(5, 1000); _writeBufferSize = (uint)_random.Next(5, 1000); + _length = _random.Next(5, 10000); _handle = GenerateRandom(_random.Next(1, 10), _random); - _offset = _random.Next(int.MinValue, -1); + _offset = _random.Next(-_length, -1); _attributes = SftpFileAttributes.Empty; } protected override void SetupMocks() { SftpSessionMock.InSequence(MockSequence) - .Setup(p => p.RequestOpen(_path, Flags.Read | Flags.CreateNewOrOpen, false)) + .Setup(session => session.RequestOpen(_path, Flags.Write | Flags.CreateNewOrOpen, false)) .Returns(_handle); SftpSessionMock.InSequence(MockSequence) - .Setup(p => p.CalculateOptimalReadLength((uint)_bufferSize)) + .Setup(session => session.CalculateOptimalReadLength((uint)_bufferSize)) .Returns(_readBufferSize); SftpSessionMock.InSequence(MockSequence) - .Setup(p => p.CalculateOptimalWriteLength((uint)_bufferSize, _handle)) + .Setup(session => session.CalculateOptimalWriteLength((uint)_bufferSize, _handle)) .Returns(_writeBufferSize); - SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); SftpSessionMock.InSequence(MockSequence) - .Setup(p => p.RequestFStat(_handle, false)) + .Setup(session => session.IsOpen) + .Returns(true); + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.RequestFStat(_handle, false)) + .Returns(_attributes); + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.RequestFSetStat(_handle, _attributes)); + SftpSessionMock.InSequence(MockSequence).Setup(session => session.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.RequestFStat(_handle, false)) .Returns(_attributes); } @@ -60,43 +70,34 @@ protected override void Arrange() base.Arrange(); _target = new SftpFileStream(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize); + _target.SetLength(_length); } protected override void Act() { - try - { - _target.Seek(_offset, SeekOrigin.End); - Assert.Fail(); - } - catch (EndOfStreamException ex) - { - _actualException = ex; - } + _actual = _target.Seek(_offset, SeekOrigin.End); } [TestMethod] - public void SeekShouldHaveThrownEndOfStreamException() + public void SeekShouldHaveReturnedOffset() { - Assert.IsNotNull(_actualException); - Assert.IsNull(_actualException.InnerException); - Assert.AreEqual("Attempted to read past the end of the stream.", _actualException.Message); + Assert.AreEqual(_attributes.Size + _offset, _actual); } [TestMethod] - public void IsOpenOnSftpSessionShouldHaveBeenInvokedOnce() + public void IsOpenOnSftpSessionShouldHaveBeenInvokedTwice() { - SftpSessionMock.Verify(p => p.IsOpen, Times.Once); + SftpSessionMock.Verify(session => session.IsOpen, Times.Exactly(2)); } [TestMethod] - public void PositionShouldReturnZero() + public void PositionShouldReturnOffset() { - SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence).Setup(session => session.IsOpen).Returns(true); - Assert.AreEqual(0L, _target.Position); + Assert.AreEqual(_attributes.Size + _offset, _target.Position); - SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(2)); + SftpSessionMock.Verify(session => session.IsOpen, Times.Exactly(3)); } } } diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetPositive.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetPositive.cs index 76fc6e8c5..506342f1a 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetPositive.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetPositive.cs @@ -16,6 +16,7 @@ public class SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndO private int _bufferSize; private uint _readBufferSize; private uint _writeBufferSize; + private int _length; private byte[] _handle; private SftpFileStream _target; private int _offset; @@ -29,10 +30,11 @@ protected override void SetupData() _random = new Random(); _path = _random.Next().ToString(); _fileMode = FileMode.OpenOrCreate; - _fileAccess = FileAccess.Read; + _fileAccess = FileAccess.Write; _bufferSize = _random.Next(5, 1000); _readBufferSize = (uint)_random.Next(5, 1000); _writeBufferSize = (uint)_random.Next(5, 1000); + _length = _random.Next(5, 10000); _handle = GenerateRandom(_random.Next(1, 10), _random); _offset = _random.Next(1, int.MaxValue); _attributes = SftpFileAttributes.Empty; @@ -41,17 +43,25 @@ protected override void SetupData() protected override void SetupMocks() { SftpSessionMock.InSequence(MockSequence) - .Setup(p => p.RequestOpen(_path, Flags.Read | Flags.CreateNewOrOpen, false)) + .Setup(session => session.RequestOpen(_path, Flags.Write | Flags.CreateNewOrOpen, false)) .Returns(_handle); SftpSessionMock.InSequence(MockSequence) - .Setup(p => p.CalculateOptimalReadLength((uint)_bufferSize)) + .Setup(session => session.CalculateOptimalReadLength((uint)_bufferSize)) .Returns(_readBufferSize); SftpSessionMock.InSequence(MockSequence) - .Setup(p => p.CalculateOptimalWriteLength((uint)_bufferSize, _handle)) + .Setup(session => session.CalculateOptimalWriteLength((uint)_bufferSize, _handle)) .Returns(_writeBufferSize); - SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); SftpSessionMock.InSequence(MockSequence) - .Setup(p => p.RequestFStat(_handle, false)) + .Setup(session => session.IsOpen) + .Returns(true); + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.RequestFStat(_handle, false)) + .Returns(_attributes); + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.RequestFSetStat(_handle, _attributes)); + SftpSessionMock.InSequence(MockSequence).Setup(session => session.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.RequestFStat(_handle, false)) .Returns(_attributes); } @@ -60,6 +70,7 @@ protected override void Arrange() base.Arrange(); _target = new SftpFileStream(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize); + _target.SetLength(_length); } protected override void Act() @@ -70,23 +81,23 @@ protected override void Act() [TestMethod] public void SeekShouldHaveReturnedOffset() { - Assert.AreEqual(_offset, _actual); + Assert.AreEqual(_attributes.Size + _offset, _actual); } [TestMethod] - public void IsOpenOnSftpSessionShouldHaveBeenInvokedOnce() + public void IsOpenOnSftpSessionShouldHaveBeenInvokedTwice() { - SftpSessionMock.Verify(p => p.IsOpen, Times.Once); + SftpSessionMock.Verify(session => session.IsOpen, Times.Exactly(2)); } [TestMethod] public void PositionShouldReturnOffset() { - SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence).Setup(session => session.IsOpen).Returns(true); - Assert.AreEqual(_offset, _target.Position); + Assert.AreEqual(_attributes.Size + _offset, _target.Position); - SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(2)); + SftpSessionMock.Verify(session => session.IsOpen, Times.Exactly(3)); } } } diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetZero.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetZero.cs index 02313b95a..4791acf85 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetZero.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetZero.cs @@ -16,8 +16,10 @@ public class SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndO private int _bufferSize; private uint _readBufferSize; private uint _writeBufferSize; + private int _length; private byte[] _handle; private SftpFileStream _target; + private int _offset; private SftpFileAttributes _attributes; private long _actual; @@ -28,28 +30,38 @@ protected override void SetupData() _random = new Random(); _path = _random.Next().ToString(); _fileMode = FileMode.OpenOrCreate; - _fileAccess = FileAccess.Read; + _fileAccess = FileAccess.Write; _bufferSize = _random.Next(5, 1000); _readBufferSize = (uint)_random.Next(5, 1000); _writeBufferSize = (uint)_random.Next(5, 1000); + _length = _random.Next(5, 10000); _handle = GenerateRandom(_random.Next(1, 10), _random); + _offset = 0; _attributes = SftpFileAttributes.Empty; } protected override void SetupMocks() { SftpSessionMock.InSequence(MockSequence) - .Setup(p => p.RequestOpen(_path, Flags.Read | Flags.CreateNewOrOpen, false)) + .Setup(session => session.RequestOpen(_path, Flags.Write | Flags.CreateNewOrOpen, false)) .Returns(_handle); SftpSessionMock.InSequence(MockSequence) - .Setup(p => p.CalculateOptimalReadLength((uint)_bufferSize)) + .Setup(session => session.CalculateOptimalReadLength((uint)_bufferSize)) .Returns(_readBufferSize); SftpSessionMock.InSequence(MockSequence) - .Setup(p => p.CalculateOptimalWriteLength((uint)_bufferSize, _handle)) + .Setup(session => session.CalculateOptimalWriteLength((uint)_bufferSize, _handle)) .Returns(_writeBufferSize); - SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); SftpSessionMock.InSequence(MockSequence) - .Setup(p => p.RequestFStat(_handle, false)) + .Setup(session => session.IsOpen) + .Returns(true); + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.RequestFStat(_handle, false)) + .Returns(_attributes); + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.RequestFSetStat(_handle, _attributes)); + SftpSessionMock.InSequence(MockSequence).Setup(session => session.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.RequestFStat(_handle, false)) .Returns(_attributes); } @@ -58,33 +70,34 @@ protected override void Arrange() base.Arrange(); _target = new SftpFileStream(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize); + _target.SetLength(_length); } protected override void Act() { - _actual = _target.Seek(0L, SeekOrigin.End); + _actual = _target.Seek(_offset, SeekOrigin.End); } [TestMethod] - public void SeekShouldHaveReturnedZero() + public void SeekShouldHaveReturnedSize() { - Assert.AreEqual(0L, _actual); + Assert.AreEqual(_attributes.Size, _actual); } [TestMethod] - public void IsOpenOnSftpSessionShouldHaveBeenInvokedOnce() + public void IsOpenOnSftpSessionShouldHaveBeenInvokedTwice() { - SftpSessionMock.Verify(p => p.IsOpen, Times.Once); + SftpSessionMock.Verify(session => session.IsOpen, Times.Exactly(2)); } [TestMethod] - public void PositionShouldReturnZero() + public void PositionShouldReturnSize() { - SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence).Setup(session => session.IsOpen).Returns(true); - Assert.AreEqual(0L, _target.Position); + Assert.AreEqual(_attributes.Size, _target.Position); - SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(2)); + SftpSessionMock.Verify(session => session.IsOpen, Times.Exactly(3)); } } }