Răsfoiți Sursa

SftpFileStream: Position in stream should be left untouched when clearing read buffer.

Gert Driesen 8 ani în urmă
părinte
comite
79c9a4baea

+ 22 - 1
src/Renci.SshNet.Tests.NET35/Renci.SshNet.Tests.NET35.csproj

@@ -1200,6 +1200,24 @@
     <Compile Include="..\Renci.SshNet.Tests\Classes\Sftp\SftpFileStreamTest_Finalize_SessionOpen.cs">
       <Link>Classes\Sftp\SftpFileStreamTest_Finalize_SessionOpen.cs</Link>
     </Compile>
+    <Compile Include="..\Renci.SshNet.Tests\Classes\Sftp\SftpFileStreamTest_Flush_ReadMode_DataInBuffer_NotReadFromBuffer.cs">
+      <Link>Classes\Sftp\SftpFileStreamTest_Flush_ReadMode_DataInBuffer_NotReadFromBuffer.cs</Link>
+    </Compile>
+    <Compile Include="..\Renci.SshNet.Tests\Classes\Sftp\SftpFileStreamTest_Flush_ReadMode_DataInBuffer_ReadFromBuffer.cs">
+      <Link>Classes\Sftp\SftpFileStreamTest_Flush_ReadMode_DataInBuffer_ReadFromBuffer.cs</Link>
+    </Compile>
+    <Compile Include="..\Renci.SshNet.Tests\Classes\Sftp\SftpFileStreamTest_Flush_ReadMode_NoDataInBuffer.cs">
+      <Link>Classes\Sftp\SftpFileStreamTest_Flush_ReadMode_NoDataInBuffer.cs</Link>
+    </Compile>
+    <Compile Include="..\Renci.SshNet.Tests\Classes\Sftp\SftpFileStreamTest_Flush_SessionNotOpen.cs">
+      <Link>Classes\Sftp\SftpFileStreamTest_Flush_SessionNotOpen.cs</Link>
+    </Compile>
+    <Compile Include="..\Renci.SshNet.Tests\Classes\Sftp\SftpFileStreamTest_Flush_WriteMode_DataInBuffer.cs">
+      <Link>Classes\Sftp\SftpFileStreamTest_Flush_WriteMode_DataInBuffer.cs</Link>
+    </Compile>
+    <Compile Include="..\Renci.SshNet.Tests\Classes\Sftp\SftpFileStreamTest_Flush_WriteMode_NoDataInBuffer.cs">
+      <Link>Classes\Sftp\SftpFileStreamTest_Flush_WriteMode_NoDataInBuffer.cs</Link>
+    </Compile>
     <Compile Include="..\Renci.SshNet.Tests\Classes\Sftp\SftpFileStreamTest_ReadByte_ReadMode_NoDataInWriteBufferAndNoDataInReadBuffer_Eof.cs">
       <Link>Classes\Sftp\SftpFileStreamTest_ReadByte_ReadMode_NoDataInWriteBufferAndNoDataInReadBuffer_Eof.cs</Link>
     </Compile>
@@ -1434,6 +1452,9 @@
     <Compile Include="..\Renci.SshNet.Tests\Classes\SubsystemSession_SendData_NeverConnected.cs">
       <Link>Classes\SubsystemSession_SendData_NeverConnected.cs</Link>
     </Compile>
+    <Compile Include="..\Renci.SshNet.Tests\Common\ArrayBuilder.cs">
+      <Link>Common\ArrayBuilder.cs</Link>
+    </Compile>
     <Compile Include="..\Renci.SshNet.Tests\Common\AsyncSocketListener.cs">
       <Link>Common\AsyncSocketListener.cs</Link>
     </Compile>
@@ -1527,7 +1548,7 @@
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <ProjectExtensions>
     <VisualStudio>
-      <UserProperties ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" ProjectLinkReference="c45379b9-17b1-4e89-bc2e-6d41726413e8" />
+      <UserProperties ProjectLinkReference="c45379b9-17b1-4e89-bc2e-6d41726413e8" ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" />
     </VisualStudio>
   </ProjectExtensions>
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 

+ 112 - 0
src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Flush_ReadMode_DataInBuffer_NotReadFromBuffer.cs

@@ -0,0 +1,112 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using Renci.SshNet.Sftp;
+using Renci.SshNet.Tests.Common;
+using System;
+using System.IO;
+
+namespace Renci.SshNet.Tests.Classes.Sftp
+{
+    [TestClass]
+    public class SftpFileStreamTest_Flush_ReadMode_DataInBuffer_NotReadFromBuffer : SftpFileStreamTestBase
+    {
+        private SftpFileStream _target;
+        private string _path;
+        private byte[] _handle;
+        private uint _bufferSize;
+        private uint _readBufferSize;
+        private uint _writeBufferSize;
+        private byte[] _readBytes;
+        private byte[] _serverBytes;
+
+        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 = 100;
+            _writeBufferSize = 500;
+            _readBytes = new byte[random.Next(1, (int) _readBufferSize - 10)];
+            _serverBytes = GenerateRandom(_readBytes.Length + 5); // store 5 bytes in read buffer
+        }
+
+        protected override void SetupMocks()
+        {
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.RequestOpen(_path, Flags.Read, false))
+                           .Returns(_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.RequestRead(_handle, 0UL, _readBufferSize))
+                           .Returns(_serverBytes);
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.IsOpen)
+                           .Returns(true);
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
+
+            _target = new SftpFileStream(SftpSessionMock.Object,
+                                         _path,
+                                         FileMode.Open,
+                                         FileAccess.Read,
+                                         (int)_bufferSize);
+            _target.Read(_readBytes, 0, _readBytes.Length);
+        }
+
+        protected override void Act()
+        {
+            _target.Flush();
+        }
+
+        [TestMethod]
+        public void PositionShouldReturnSameValueAsBeforeFlush()
+        {
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.IsOpen)
+                           .Returns(true);
+
+            Assert.AreEqual(_readBytes.Length, _target.Position);
+
+            SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(3));
+        }
+
+        [TestMethod]
+        public void ReadShouldReadFromServer()
+        {
+            var serverBytes2 = GenerateRandom(5);
+            var readBytes2 = new byte[5];
+            var expectedReadBytes = new ArrayBuilder<byte>().Add(new byte[2])
+                                                            .Add(serverBytes2.Take(0, 3))
+                                                            .Build();
+
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.IsOpen)
+                           .Returns(true);
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.RequestRead(_handle, (ulong)_readBytes.Length, _readBufferSize))
+                           .Returns(serverBytes2);
+
+            var bytesRead = _target.Read(readBytes2, 2, 3);
+
+            Assert.AreEqual(3, bytesRead);
+            CollectionAssert.AreEqual(expectedReadBytes, readBytes2);
+
+            SftpSessionMock.Verify(p => p.RequestRead(_handle, (ulong)_readBytes.Length, _readBufferSize), Times.Once);
+            SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(3));
+        }
+    }
+}

+ 118 - 0
src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Flush_ReadMode_DataInBuffer_ReadFromBuffer.cs

@@ -0,0 +1,118 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using Renci.SshNet.Sftp;
+using Renci.SshNet.Tests.Common;
+using System;
+using System.IO;
+
+namespace Renci.SshNet.Tests.Classes.Sftp
+{
+    [TestClass]
+    public class SftpFileStreamTest_Flush_ReadMode_DataInBuffer_ReadFromBuffer : SftpFileStreamTestBase
+    {
+        private SftpFileStream _target;
+        private string _path;
+        private byte[] _handle;
+        private uint _bufferSize;
+        private uint _readBufferSize;
+        private uint _writeBufferSize;
+        private byte[] _readBytes1;
+        private byte[] _readBytes2;
+        private byte[] _serverBytes;
+
+        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 = 100;
+            _writeBufferSize = 500;
+            _readBytes1 = new byte[random.Next(1, (int) _readBufferSize - 10)];
+            _readBytes2 = new byte[random.Next(1, 3)];
+            _serverBytes = GenerateRandom(_readBytes1.Length + 10); // store 5 bytes in read buffer
+        }
+
+        protected override void SetupMocks()
+        {
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.RequestOpen(_path, Flags.Read, false))
+                           .Returns(_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.RequestRead(_handle, 0UL, _readBufferSize))
+                           .Returns(_serverBytes);
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.IsOpen)
+                           .Returns(true);
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.IsOpen)
+                           .Returns(true);
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
+
+            _target = new SftpFileStream(SftpSessionMock.Object,
+                                         _path,
+                                         FileMode.Open,
+                                         FileAccess.Read,
+                                         (int)_bufferSize);
+            _target.Read(_readBytes1, 0, _readBytes1.Length);
+            _target.Read(_readBytes2, 0, _readBytes2.Length);
+        }
+
+        protected override void Act()
+        {
+            _target.Flush();
+        }
+
+        [TestMethod]
+        public void PositionShouldReturnSameValueAsBeforeFlush()
+        {
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.IsOpen)
+                           .Returns(true);
+
+            Assert.AreEqual(_readBytes1.Length + _readBytes2.Length, _target.Position);
+
+            SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(4));
+        }
+
+        [TestMethod]
+        public void ReadShouldReadFromServer()
+        {
+            var serverBytes3 = GenerateRandom(5);
+            var readBytes3 = new byte[3];
+            var expectedReadBytes = new ArrayBuilder<byte>().Add(new byte[1])
+                                                            .Add(serverBytes3.Take(0, 2))
+                                                            .Build();
+
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.IsOpen)
+                           .Returns(true);
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.RequestRead(_handle, (ulong) (_readBytes1.Length + _readBytes2.Length), _readBufferSize))
+                           .Returns(serverBytes3);
+
+            var bytesRead = _target.Read(readBytes3, 1, 2);
+
+            Assert.AreEqual(2, bytesRead);
+            CollectionAssert.AreEqual(expectedReadBytes, readBytes3);
+
+            SftpSessionMock.Verify(p => p.RequestRead(_handle, (ulong)(_readBytes1.Length + _readBytes2.Length), _readBufferSize), Times.Once);
+            SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(4));
+        }
+    }
+}

+ 112 - 0
src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Flush_ReadMode_NoDataInBuffer.cs

@@ -0,0 +1,112 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using Renci.SshNet.Sftp;
+using Renci.SshNet.Tests.Common;
+using System;
+using System.IO;
+
+namespace Renci.SshNet.Tests.Classes.Sftp
+{
+    [TestClass]
+    public class SftpFileStreamTest_Flush_ReadMode_NoDataInBuffer : SftpFileStreamTestBase
+    {
+        private SftpFileStream _target;
+        private string _path;
+        private byte[] _handle;
+        private uint _bufferSize;
+        private uint _readBufferSize;
+        private uint _writeBufferSize;
+        private byte[] _readBytes;
+        private byte[] _serverBytes;
+
+        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 = 100;
+            _writeBufferSize = 500;
+            _readBytes = new byte[random.Next(1, (int) _readBufferSize)];
+            _serverBytes = GenerateRandom(_readBytes.Length);
+        }
+
+        protected override void SetupMocks()
+        {
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.RequestOpen(_path, Flags.Read, false))
+                           .Returns(_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.RequestRead(_handle, 0UL, _readBufferSize))
+                           .Returns(_serverBytes);
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.IsOpen)
+                           .Returns(true);
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
+
+            _target = new SftpFileStream(SftpSessionMock.Object,
+                                         _path,
+                                         FileMode.Open,
+                                         FileAccess.Read,
+                                         (int) _bufferSize);
+            _target.Read(_readBytes, 0, _readBytes.Length);
+        }
+
+        protected override void Act()
+        {
+            _target.Flush();
+        }
+
+        [TestMethod]
+        public void PositionShouldReturnSameValueAsBeforeFlush()
+        {
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.IsOpen)
+                           .Returns(true);
+
+            Assert.AreEqual(_readBytes.Length, _target.Position);
+
+            SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(3));
+        }
+
+        [TestMethod]
+        public void ReadShouldReadFromServer()
+        {
+            var serverBytes2 = GenerateRandom(5);
+            var readBytes2 = new byte[5];
+            var expectedReadBytes = new ArrayBuilder<byte>().Add(new byte[2])
+                                                            .Add(serverBytes2.Take(0, 3))
+                                                            .Build();
+
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.IsOpen)
+                           .Returns(true);
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.RequestRead(_handle, (ulong) _readBytes.Length, _readBufferSize))
+                           .Returns(serverBytes2);
+
+            var bytesRead = _target.Read(readBytes2, 2, 3);
+
+            Assert.AreEqual(3, bytesRead);
+            CollectionAssert.AreEqual(expectedReadBytes, readBytes2);
+
+            SftpSessionMock.Verify(p => p.RequestRead(_handle, (ulong)_readBytes.Length, _readBufferSize), Times.Once);
+            SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(3));
+        }
+    }
+}

+ 81 - 0
src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Flush_SessionNotOpen.cs

@@ -0,0 +1,81 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using Renci.SshNet.Sftp;
+using System;
+using System.IO;
+
+namespace Renci.SshNet.Tests.Classes.Sftp
+{
+    [TestClass]
+    public class SftpFileStreamTest_Flush_SessionNotOpen : SftpFileStreamTestBase
+    {
+        private SftpFileStream _target;
+        private string _path;
+        private byte[] _handle;
+        private uint _bufferSize;
+        private uint _readBufferSize;
+        private uint _writeBufferSize;
+        private ObjectDisposedException _actualException;
+
+        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;
+        }
+
+        protected override void SetupMocks()
+        {
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.RequestOpen(_path, Flags.Read, false))
+                           .Returns(_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(false);
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
+
+            _target = new SftpFileStream(SftpSessionMock.Object,
+                                         _path,
+                                         FileMode.Open,
+                                         FileAccess.Read,
+                                         (int) _bufferSize);
+        }
+
+        protected override void Act()
+        {
+            try
+            {
+                _target.Flush();
+                Assert.Fail();
+            }
+            catch (ObjectDisposedException ex)
+            {
+                _actualException = ex;
+            }
+        }
+
+        [TestMethod]
+        public void FlushShouldHaveThrownObjectDisposedException()
+        {
+            Assert.IsNotNull(_actualException);
+            Assert.IsNull(_actualException.InnerException);
+            Assert.AreEqual(string.Format("Cannot access a closed SFTP session.{0}Object name: '{1}'.", Environment.NewLine, _actualException.ObjectName), _actualException.Message);
+            Assert.AreEqual(typeof(SftpFileStream).FullName, _actualException.ObjectName);
+        }
+    }
+}

+ 149 - 0
src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Flush_WriteMode_DataInBuffer.cs

@@ -0,0 +1,149 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using Renci.SshNet.Sftp;
+using Renci.SshNet.Sftp.Responses;
+using Renci.SshNet.Tests.Common;
+using System;
+using System.IO;
+using System.Threading;
+
+namespace Renci.SshNet.Tests.Classes.Sftp
+{
+    [TestClass]
+    public class SftpFileStreamTest_Flush_WriteMode_DataInBuffer : SftpFileStreamTestBase
+    {
+        private SftpFileStream _target;
+        private string _path;
+        private byte[] _handle;
+        private uint _bufferSize;
+        private uint _readBufferSize;
+        private uint _writeBufferSize;
+        private byte[] _writeBytes1;
+        private byte[] _writeBytes2;
+        private byte[] _writeBytes3;
+        private byte[] _flushedBytes;
+
+        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 = 100;
+            _writeBufferSize = 500;
+            _writeBytes1 = GenerateRandom(_writeBufferSize);
+            _writeBytes2 = GenerateRandom(2);
+            _writeBytes3 = GenerateRandom(3);
+            _flushedBytes = null;
+        }
+
+        protected override void SetupMocks()
+        {
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.RequestOpen(_path, Flags.Read | Flags.Write, false))
+                           .Returns(_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.RequestWrite(_handle, 0UL, It.IsAny<byte[]>(), 0, _writeBytes1.Length, It.IsAny<AutoResetEvent>(), null))
+                           .Callback<byte[], ulong, byte[], int, int, AutoResetEvent, Action<SftpStatusResponse>>((handle, serverOffset, data, offset, length, wait, writeCompleted)
+                               =>
+                           {
+                               wait.Set();
+                           });
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.IsOpen)
+                           .Returns(true);
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.IsOpen)
+                           .Returns(true);
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.IsOpen)
+                           .Returns(true);
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.RequestWrite(_handle, (ulong) _writeBytes1.Length, It.IsAny<byte[]>(), 0, _writeBytes2.Length + _writeBytes3.Length, It.IsAny<AutoResetEvent>(), null))
+                           .Callback<byte[], ulong, byte[], int, int, AutoResetEvent, Action<SftpStatusResponse>>((handle, serverOffset, data, offset, length, wait, writeCompleted)
+                               =>
+                           {
+                               _flushedBytes = data.Take(offset, length);
+                               wait.Set();
+                           });
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
+
+            _target = new SftpFileStream(SftpSessionMock.Object,
+                                         _path,
+                                         FileMode.Open,
+                                         FileAccess.ReadWrite,
+                                         (int)_bufferSize);
+            _target.Write(_writeBytes1, 0, _writeBytes1.Length);
+            _target.Write(_writeBytes2, 0, _writeBytes2.Length);
+            _target.Write(_writeBytes3, 0, _writeBytes3.Length);
+        }
+
+        protected override void Act()
+        {
+            _target.Flush();
+        }
+
+        [TestMethod]
+        public void PositionShouldReturnSameValueAsBeforeFlush()
+        {
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.IsOpen)
+                           .Returns(true);
+
+            Assert.AreEqual(_writeBytes1.Length + _writeBytes2.Length + _writeBytes3.Length, _target.Position);
+
+            SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(5));
+        }
+
+        [TestMethod]
+        public void BufferedBytesShouldHaveBeenWrittenToTheServer()
+        {
+            var expected = new ArrayBuilder<byte>().Add(_writeBytes2)
+                                                   .Add(_writeBytes3)
+                                                   .Build();
+
+            Assert.IsNotNull(_flushedBytes);
+            CollectionAssert.AreEqual(expected, _flushedBytes);
+        }
+
+        [TestMethod]
+        public void ReadShouldReadFromServer()
+        {
+            var serverBytes = GenerateRandom(5);
+            var readBytes = new byte[5];
+            var expectedReadBytes = new ArrayBuilder<byte>().Add(new byte[2])
+                                                            .Add(serverBytes.Take(0, 3))
+                                                            .Build();
+
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.IsOpen)
+                           .Returns(true);
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.RequestRead(_handle, (ulong) (_writeBytes1.Length + _writeBytes2.Length + _writeBytes3.Length), _readBufferSize))
+                           .Returns(serverBytes);
+
+            var bytesRead = _target.Read(readBytes, 2, 3);
+
+            Assert.AreEqual(3, bytesRead);
+            CollectionAssert.AreEqual(expectedReadBytes, readBytes);
+
+            SftpSessionMock.Verify(p => p.RequestRead(_handle, (ulong)(_writeBytes1.Length + _writeBytes2.Length + _writeBytes3.Length), _readBufferSize), Times.Once);
+            SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(5));
+        }
+    }
+}

+ 117 - 0
src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Flush_WriteMode_NoDataInBuffer.cs

@@ -0,0 +1,117 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using Renci.SshNet.Sftp;
+using Renci.SshNet.Sftp.Responses;
+using Renci.SshNet.Tests.Common;
+using System;
+using System.IO;
+using System.Threading;
+
+namespace Renci.SshNet.Tests.Classes.Sftp
+{
+    [TestClass]
+    public class SftpFileStreamTest_Flush_WriteMode_NoDataInBuffer : SftpFileStreamTestBase
+    {
+        private SftpFileStream _target;
+        private string _path;
+        private byte[] _handle;
+        private uint _bufferSize;
+        private uint _readBufferSize;
+        private uint _writeBufferSize;
+        private byte[] _writeBytes;
+        private byte[] _requestWriteBytes;
+
+        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 = 100;
+            _writeBufferSize = 500;
+            _writeBytes = GenerateRandom(_writeBufferSize);
+        }
+
+        protected override void SetupMocks()
+        {
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.RequestOpen(_path, Flags.Read | Flags.Write, false))
+                           .Returns(_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.RequestWrite(_handle, 0UL, It.IsAny<byte[]>(), 0, _writeBytes.Length, It.IsAny<AutoResetEvent>(), null))
+                           .Callback<byte[], ulong, byte[], int, int, AutoResetEvent, Action<SftpStatusResponse>>((handle, serverOffset, data, offset, length, wait, writeCompleted)
+                               =>
+                           {
+                               wait.Set();
+                           });
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.IsOpen)
+                           .Returns(true);
+        }
+
+        protected override void Arrange()
+        {
+            base.Arrange();
+
+            _target = new SftpFileStream(SftpSessionMock.Object,
+                                         _path,
+                                         FileMode.Open,
+                                         FileAccess.ReadWrite,
+                                         (int) _bufferSize);
+            _target.Write(_writeBytes, 0, _writeBytes.Length);
+        }
+
+        protected override void Act()
+        {
+            _target.Flush();
+        }
+
+        [TestMethod]
+        public void PositionShouldReturnSameValueAsBeforeFlush()
+        {
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.IsOpen)
+                           .Returns(true);
+
+            Assert.AreEqual(_writeBytes.Length, _target.Position);
+
+            SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(3));
+        }
+
+        [TestMethod]
+        public void ReadShouldReadFromServer()
+        {
+            var serverBytes = GenerateRandom(5);
+            var readBytes = new byte[5];
+            var expectedReadBytes = new ArrayBuilder<byte>().Add(new byte[2])
+                                                            .Add(serverBytes.Take(0, 3))
+                                                            .Build();
+
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.IsOpen)
+                           .Returns(true);
+            SftpSessionMock.InSequence(MockSequence)
+                           .Setup(p => p.RequestRead(_handle, (ulong) _writeBytes.Length, _readBufferSize))
+                           .Returns(serverBytes);
+
+            var bytesRead = _target.Read(readBytes, 2, 3);
+
+            Assert.AreEqual(3, bytesRead);
+            CollectionAssert.AreEqual(expectedReadBytes, readBytes);
+
+            SftpSessionMock.Verify(p => p.RequestRead(_handle, (ulong) _writeBytes.Length, _readBufferSize), Times.Once);
+            SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(3));
+        }
+    }
+}

+ 26 - 17
src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_SetLength_DataInReadBuffer_NewLengthGreatherThanPosition.cs

@@ -12,7 +12,7 @@ namespace Renci.SshNet.Tests.Classes.Sftp
 {
     /// <summary>
     /// - In read mode
-    /// - Bytes in (read) buffer
+    /// - Bytes read from (read) buffer
     /// - New length greater than client position and greater than server position
     /// </summary>
     [TestClass]
@@ -30,7 +30,8 @@ namespace Renci.SshNet.Tests.Classes.Sftp
         private SftpFileAttributes _fileAttributes;
         private SftpFileAttributes _originalFileAttributes;
         private SftpFileAttributes _newFileAttributes;
-        private byte[] _readBytes;
+        private byte[] _readBytes1;
+        private byte[] _readBytes2;
         private byte[] _actualReadBytes;
 
         protected override void SetupData()
@@ -42,16 +43,17 @@ namespace Renci.SshNet.Tests.Classes.Sftp
             _bufferSize = (uint) random.Next(1, 1000);
             _readBufferSize = (uint) random.Next(1, 1000);
             _writeBufferSize = (uint) random.Next(100, 1000);
-            _readBytes = new byte[5];
-            _actualReadBytes = GenerateRandom(_readBytes.Length, random);
-            _length = _readBytes.Length + 2;
+            _readBytes1 = new byte[5];
+            _readBytes2 = new byte[random.Next(1, 3)];
+            _actualReadBytes = GenerateRandom(_readBytes1.Length + _readBytes2.Length + 2, random); // server returns more bytes than the caller requested
+            _length = _readBytes1.Length + _readBytes2.Length + 5;
 
             _fileAttributes = new SftpFileAttributesBuilder().WithExtension("X", "ABC")
                                                              .WithExtension("V", "VValue")
                                                              .WithGroupId(random.Next())
                                                              .WithLastAccessTime(DateTime.Now.AddSeconds(random.Next()))
                                                              .WithLastWriteTime(DateTime.Now.AddSeconds(random.Next()))
-                                                             .WithPermissions((uint)random.Next())
+                                                             .WithPermissions((uint) random.Next())
                                                              .WithSize(_length + 100)
                                                              .WithUserId(random.Next())
                                                              .Build();
@@ -80,6 +82,9 @@ namespace Renci.SshNet.Tests.Classes.Sftp
             SftpSessionMock.InSequence(_sequence)
                            .Setup(p => p.IsOpen)
                            .Returns(true);
+            SftpSessionMock.InSequence(_sequence)
+                           .Setup(p => p.IsOpen)
+                           .Returns(true);
             SftpSessionMock.InSequence(_sequence)
                            .Setup(p => p.RequestFStat(_handle, false))
                            .Returns(_fileAttributes);
@@ -93,7 +98,8 @@ namespace Renci.SshNet.Tests.Classes.Sftp
             base.Arrange();
 
             _sftpFileStream = new SftpFileStream(SftpSessionMock.Object, _path, FileMode.Open, FileAccess.ReadWrite, (int)_bufferSize);
-            _sftpFileStream.Read(_readBytes, 0, _readBytes.Length);
+            _sftpFileStream.Read(_readBytes1, 0, _readBytes1.Length);
+            _sftpFileStream.Read(_readBytes2, 0, _readBytes2.Length); // this will return bytes from the buffer
         }
 
         protected override void Act()
@@ -106,9 +112,9 @@ namespace Renci.SshNet.Tests.Classes.Sftp
         {
             SftpSessionMock.InSequence(_sequence).Setup(p => p.IsOpen).Returns(true);
 
-            Assert.AreEqual(_readBytes.Length, _sftpFileStream.Position);
+            Assert.AreEqual(_readBytes1.Length + _readBytes2.Length, _sftpFileStream.Position);
 
-            SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(3));
+            SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(4));
         }
 
         [TestMethod]
@@ -135,35 +141,38 @@ namespace Renci.SshNet.Tests.Classes.Sftp
         {
             SftpSessionMock.InSequence(_sequence).Setup(p => p.IsOpen).Returns(true);
             SftpSessionMock.InSequence(_sequence)
-                           .Setup(p => p.RequestRead(_handle, (uint) _readBytes.Length, _readBufferSize))
+                           .Setup(p => p.RequestRead(_handle, (uint) (_readBytes1.Length + _readBytes2.Length), _readBufferSize))
                            .Returns(new byte[] { 0x0f });
 
             var byteRead = _sftpFileStream.ReadByte();
 
             Assert.AreEqual(0x0f, byteRead);
 
-            SftpSessionMock.Verify(p => p.RequestRead(_handle, (uint) _readBytes.Length, _readBufferSize), Times.Once);
-            SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(3));
+            SftpSessionMock.Verify(p => p.RequestRead(_handle, (uint)(_readBytes1.Length + _readBytes2.Length), _readBufferSize), Times.Once);
+            SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(4));
         }
 
         [TestMethod]
         public void WriteShouldStartFromSamePositionAsBeforeSetLength()
         {
-            var bytesToWrite = GenerateRandom(5);
+            var bytesToWrite = GenerateRandom(_writeBufferSize);
+            byte[] bytesWritten = null;
 
-            SftpSessionMock.InSequence(_sequence).Setup(p => p.IsOpen).Returns(true);
             SftpSessionMock.InSequence(_sequence).Setup(p => p.IsOpen).Returns(true);
             SftpSessionMock.InSequence(_sequence)
-                           .Setup(p => p.RequestWrite(_handle, (uint) _readBytes.Length, It.IsAny<byte[]>(), 0, bytesToWrite.Length, It.IsAny<AutoResetEvent>(), null))
+                           .Setup(p => p.RequestWrite(_handle, (uint) (_readBytes1.Length + _readBytes2.Length), It.IsAny<byte[]>(), 0, bytesToWrite.Length, It.IsAny<AutoResetEvent>(), null))
                            .Callback<byte[], ulong, byte[], int, int, AutoResetEvent, Action<SftpStatusResponse>>((handle, serverOffset, data, offset, length, wait, writeCompleted) =>
                            {
+                               bytesWritten = data.Take(offset, length);
                                wait.Set();
                            });
 
             _sftpFileStream.Write(bytesToWrite, 0, bytesToWrite.Length);
-            _sftpFileStream.Flush();
 
-            SftpSessionMock.Verify(p => p.RequestWrite(_handle, (uint) _readBytes.Length, It.IsAny<byte[]>(), 0, bytesToWrite.Length, It.IsAny<AutoResetEvent>(), null), Times.Once);
+            Assert.IsNotNull(bytesWritten);
+            CollectionAssert.AreEqual(bytesToWrite, bytesWritten);
+
+            SftpSessionMock.Verify(p => p.RequestWrite(_handle, (uint)(_readBytes1.Length + _readBytes2.Length), It.IsAny<byte[]>(), 0, bytesToWrite.Length, It.IsAny<AutoResetEvent>(), null), Times.Once);
             SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(4));
         }
     }

+ 10 - 7
src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_SetLength_DataInReadBuffer_NewLengthLessThanPosition.cs

@@ -13,8 +13,8 @@ namespace Renci.SshNet.Tests.Classes.Sftp
 {
     /// <summary>
     /// - In read mode
-    /// - Bytes in (read) buffer
-    /// - New length less than client position and greater than server position
+    /// - Bytes in (read) buffer, but not read from
+    /// - New length less than client position and less than server position
     /// </summary>
     [TestClass]
     public class SftpFileStreamTest_SetLength_DataInReadBuffer_NewLengthLessThanPosition : SftpFileStreamTestBase
@@ -44,7 +44,7 @@ namespace Renci.SshNet.Tests.Classes.Sftp
             _readBufferSize = (uint)random.Next(1, 1000);
             _writeBufferSize = (uint)random.Next(100, 1000);
             _readBytes = new byte[5];
-            _actualReadBytes = GenerateRandom(_readBytes.Length, random);
+            _actualReadBytes = GenerateRandom(_readBytes.Length + 2, random); // add 2 bytes in read buffer
             _length = _readBytes.Length - 2;
 
             _fileAttributes = new SftpFileAttributesBuilder().WithExtension("X", "ABC")
@@ -150,22 +150,25 @@ namespace Renci.SshNet.Tests.Classes.Sftp
         [TestMethod]
         public void WriteShouldStartFromEndOfStream()
         {
-            var bytesToWrite = GenerateRandom(5);
+            var bytesToWrite = GenerateRandom(_writeBufferSize);
+            byte[] bytesWritten = null;
 
-            SftpSessionMock.InSequence(_sequence).Setup(p => p.IsOpen).Returns(true);
             SftpSessionMock.InSequence(_sequence).Setup(p => p.IsOpen).Returns(true);
             SftpSessionMock.InSequence(_sequence)
                            .Setup(p => p.RequestWrite(_handle, (uint) _length, It.IsAny<byte[]>(), 0, bytesToWrite.Length, It.IsAny<AutoResetEvent>(), null))
                            .Callback<byte[], ulong, byte[], int, int, AutoResetEvent, Action<SftpStatusResponse>>((handle, serverOffset, data, offset, length, wait, writeCompleted) =>
                            {
+                               bytesWritten = data.Take(offset, length);
                                wait.Set();
                            });
 
             _sftpFileStream.Write(bytesToWrite, 0, bytesToWrite.Length);
-            _sftpFileStream.Flush();
+
+            Assert.IsNotNull(bytesWritten);
+            CollectionAssert.AreEqual(bytesToWrite, bytesWritten);
 
             SftpSessionMock.Verify(p => p.RequestWrite(_handle, (uint)_length, It.IsAny<byte[]>(), 0, bytesToWrite.Length, It.IsAny<AutoResetEvent>(), null), Times.Once);
-            SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(4));
+            SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(3));
         }
     }
 }

+ 8 - 5
src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_SetLength_DataInWriteBuffer_NewLengthGreatherThanPosition.cs

@@ -172,22 +172,25 @@ namespace Renci.SshNet.Tests.Classes.Sftp
         [TestMethod]
         public void WriteShouldStartFromSamePositionAsBeforeSetLength()
         {
-            var bytesToWrite = GenerateRandom(5);
+            var bytesToWrite = GenerateRandom(_writeBufferSize);
+            byte[] bytesWritten = null;
 
-            SftpSessionMock.InSequence(_sequence).Setup(p => p.IsOpen).Returns(true);
             SftpSessionMock.InSequence(_sequence).Setup(p => p.IsOpen).Returns(true);
             SftpSessionMock.InSequence(_sequence)
-                           .Setup(p => p.RequestWrite(_handle, (uint)(_readBytes.Length + _writeBytes.Length), It.IsAny<byte[]>(), 0, bytesToWrite.Length, It.IsAny<AutoResetEvent>(), null))
+                           .Setup(p => p.RequestWrite(_handle, (uint) (_readBytes.Length + _writeBytes.Length), It.IsAny<byte[]>(), 0, bytesToWrite.Length, It.IsAny<AutoResetEvent>(), null))
                            .Callback<byte[], ulong, byte[], int, int, AutoResetEvent, Action<SftpStatusResponse>>((handle, serverOffset, data, offset, length, wait, writeCompleted) =>
                                 {
+                                    bytesWritten = data.Take(offset, length);
                                     wait.Set();
                                 });
 
             _sftpFileStream.Write(bytesToWrite, 0, bytesToWrite.Length);
-            _sftpFileStream.Flush();
+
+            Assert.IsNotNull(bytesWritten);
+            CollectionAssert.AreEqual(bytesToWrite, bytesWritten);
 
             SftpSessionMock.Verify(p => p.RequestWrite(_handle, (uint) (_readBytes.Length + _writeBytes.Length), It.IsAny<byte[]>(), 0, bytesToWrite.Length, It.IsAny<AutoResetEvent>(), null), Times.Once);
-            SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(5));
+            SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(4));
         }
     }
 }

+ 8 - 5
src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_SetLength_DataInWriteBuffer_NewLengthLessThanPosition.cs

@@ -93,7 +93,7 @@ namespace Renci.SshNet.Tests.Classes.Sftp
                            .Callback<byte[], ulong, byte[], int, int, AutoResetEvent, Action<SftpStatusResponse>>((handle, serverOffset, data, offset, length, wait, writeCompleted)
                                =>
                                    {
-                                       _actualWrittenBytes = data.Take(0, _writeBytes.Length);
+                                       _actualWrittenBytes = data.Take(offset, length);
                                        wait.Set();
                                    });
             SftpSessionMock.InSequence(_sequence)
@@ -173,22 +173,25 @@ namespace Renci.SshNet.Tests.Classes.Sftp
         [TestMethod]
         public void WriteShouldStartFromEndOfStream()
         {
-            var bytesToWrite = GenerateRandom(5);
+            var bytesToWrite = GenerateRandom(_writeBufferSize);
+            byte[] bytesWritten = null;
 
-            SftpSessionMock.InSequence(_sequence).Setup(p => p.IsOpen).Returns(true);
             SftpSessionMock.InSequence(_sequence).Setup(p => p.IsOpen).Returns(true);
             SftpSessionMock.InSequence(_sequence)
                            .Setup(p => p.RequestWrite(_handle, (uint) _length, It.IsAny<byte[]>(), 0, bytesToWrite.Length, It.IsAny<AutoResetEvent>(), null))
                            .Callback<byte[], ulong, byte[], int, int, AutoResetEvent, Action<SftpStatusResponse>>((handle, serverOffset, data, offset, length, wait, writeCompleted) =>
                            {
+                               bytesWritten = data.Take(offset, length);
                                wait.Set();
                            });
 
             _sftpFileStream.Write(bytesToWrite, 0, bytesToWrite.Length);
-            _sftpFileStream.Flush();
+
+            Assert.IsNotNull(bytesWritten);
+            CollectionAssert.AreEqual(bytesToWrite, bytesWritten);
 
             SftpSessionMock.Verify(p => p.RequestWrite(_handle, (uint) _length, It.IsAny<byte[]>(), 0, bytesToWrite.Length, It.IsAny<AutoResetEvent>(), null), Times.Once);
-            SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(5));
+            SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(4));
         }
     }
 }

+ 31 - 0
src/Renci.SshNet.Tests/Common/ArrayBuilder.cs

@@ -0,0 +1,31 @@
+using System.Collections.Generic;
+
+namespace Renci.SshNet.Tests.Common
+{
+    public class ArrayBuilder<T>
+    {
+        private List<T> _buffer;
+
+        public ArrayBuilder()
+        {
+            _buffer = new List<T>();
+        }
+
+        public ArrayBuilder<T> Add(T[] array)
+        {
+            return Add(array, 0, array.Length);
+        }
+
+        public ArrayBuilder<T> Add(T[] array, int index, int length)
+        {
+            for (var i = 0; i < length; i++)
+                _buffer.Add(array[index + i]);
+            return this;
+        }
+
+        public T[] Build()
+        {
+            return _buffer.ToArray();
+        }
+    }
+}

+ 7 - 0
src/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj

@@ -434,6 +434,12 @@
     <Compile Include="Classes\Sftp\Responses\SftpVersionResponseTest.cs" />
     <Compile Include="Classes\Sftp\SftpFileStreamTest_Dispose_Disposed.cs" />
     <Compile Include="Classes\Sftp\SftpFileStreamTest_Finalize_SessionOpen.cs" />
+    <Compile Include="Classes\Sftp\SftpFileStreamTest_Flush_ReadMode_DataInBuffer_NotReadFromBuffer.cs" />
+    <Compile Include="Classes\Sftp\SftpFileStreamTest_Flush_ReadMode_DataInBuffer_ReadFromBuffer.cs" />
+    <Compile Include="Classes\Sftp\SftpFileStreamTest_Flush_ReadMode_NoDataInBuffer.cs" />
+    <Compile Include="Classes\Sftp\SftpFileStreamTest_Flush_SessionNotOpen.cs" />
+    <Compile Include="Classes\Sftp\SftpFileStreamTest_Flush_WriteMode_DataInBuffer.cs" />
+    <Compile Include="Classes\Sftp\SftpFileStreamTest_Flush_WriteMode_NoDataInBuffer.cs" />
     <Compile Include="Classes\Sftp\SftpFileStreamTest_ReadByte_ReadMode_NoDataInWriteBufferAndNoDataInReadBuffer_LessDataThanReadBufferSizeAvailable.cs" />
     <Compile Include="Classes\Sftp\SftpFileStreamTest_Read_ReadMode_NoDataInReaderBufferAndReadLessBytesFromServerThanCountAndLessThanBufferSize.cs" />
     <Compile Include="Classes\Sftp\SftpFileStreamTest_Read_ReadMode_NoDataInReaderBufferAndReadLessBytesFromServerThanCountAndEqualToBufferSize.cs" />
@@ -516,6 +522,7 @@
     <Compile Include="Classes\SubsystemSession_SendData_Disconnected.cs" />
     <Compile Include="Classes\SubsystemSession_SendData_Disposed.cs" />
     <Compile Include="Classes\SubsystemSession_SendData_NeverConnected.cs" />
+    <Compile Include="Common\ArrayBuilder.cs" />
     <Compile Include="Common\AsyncSocketListener.cs" />
     <Compile Include="Common\DictionaryAssert.cs" />
     <Compile Include="Common\Extensions.cs" />

+ 2 - 9
src/Renci.SshNet/Sftp/SftpFileStream.cs

@@ -837,15 +837,8 @@ namespace Renci.SshNet.Sftp
         /// </summary>
         private void FlushReadBuffer()
         {
-            if (_canSeek)
-            {
-                if (_bufferPosition < _bufferLen)
-                {
-                    _position -= _bufferPosition;
-                }
-                _bufferPosition = 0;
-                _bufferLen = 0;
-            }
+            _bufferPosition = 0;
+            _bufferLen = 0;
         }
 
         /// <summary>