Skip to content

Commit 6fd1cc7

Browse files
committed
Update Read(byte[] buffer, int offset, int count) to not write bytes to read buffer when the read buffer is empty and count is greater than the number of bytes read from the server.
Lazily initialize read and write buffer.
1 parent 40efaa6 commit 6fd1cc7

4 files changed

+109
-93
lines changed
Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace Renci.SshNet.Tests.Classes.Sftp
88
{
99
[TestClass]
1010
//[Ignore]
11-
public class SftpFileStreamTest_Seek_PositionedAtMiddleOfStream_OriginBeginAndOffsetZero_OutsideOfReadBuffer : SftpFileStreamTestBase
11+
public class SftpFileStreamTest_Seek_PositionedAtMiddleOfStream_OriginBeginAndOffsetZero_NoBuffering : SftpFileStreamTestBase
1212
{
1313
private Random _random;
1414
private string _path;
@@ -21,8 +21,7 @@ public class SftpFileStreamTest_Seek_PositionedAtMiddleOfStream_OriginBeginAndOf
2121
private SftpFileStream _target;
2222
private long _actual;
2323
private byte[] _buffer;
24-
private byte[] _serverData1;
25-
private byte[] _serverData2;
24+
private byte[] _serverData;
2625

2726
protected override void SetupData()
2827
{
@@ -36,9 +35,8 @@ protected override void SetupData()
3635
_readBufferSize = 20;
3736
_writeBufferSize = (uint) _random.Next(5, 1000);
3837
_handle = GenerateRandom(_random.Next(1, 10), _random);
39-
_buffer = new byte[_readBufferSize + 1];
40-
_serverData1 = GenerateRandom((int) _readBufferSize, _random);
41-
_serverData2 = GenerateRandom(10, _random);
38+
_buffer = new byte[_readBufferSize];
39+
_serverData = GenerateRandom(_buffer.Length, _random);
4240
}
4341

4442
protected override void SetupMocks()
@@ -47,20 +45,17 @@ protected override void SetupMocks()
4745
.Setup(p => p.RequestOpen(_path, Flags.Read | Flags.CreateNewOrOpen, false))
4846
.Returns(_handle);
4947
SftpSessionMock.InSequence(MockSequence)
50-
.Setup(p => p.CalculateOptimalReadLength((uint) _bufferSize))
48+
.Setup(p => p.CalculateOptimalReadLength((uint)_bufferSize))
5149
.Returns(_readBufferSize);
5250
SftpSessionMock.InSequence(MockSequence)
53-
.Setup(p => p.CalculateOptimalWriteLength((uint) _bufferSize, _handle))
51+
.Setup(p => p.CalculateOptimalWriteLength((uint)_bufferSize, _handle))
5452
.Returns(_writeBufferSize);
5553
SftpSessionMock.InSequence(MockSequence)
5654
.Setup(p => p.IsOpen)
5755
.Returns(true);
5856
SftpSessionMock.InSequence(MockSequence)
5957
.Setup(p => p.RequestRead(_handle, 0UL, _readBufferSize))
60-
.Returns(_serverData1);
61-
SftpSessionMock.InSequence(MockSequence)
62-
.Setup(p => p.RequestRead(_handle, _readBufferSize, _readBufferSize))
63-
.Returns(_serverData2);
58+
.Returns(_serverData);
6459
SftpSessionMock.InSequence(MockSequence)
6560
.Setup(p => p.IsOpen)
6661
.Returns(true);
@@ -104,21 +99,24 @@ public void IsOpenOnSftpSessionShouldHaveBeenInvokedTwice()
10499
}
105100

106101
[TestMethod]
107-
public void ReadShouldReadFromServer()
102+
public void ReadShouldReturnReadBytesFromServer()
108103
{
109104
SftpSessionMock.InSequence(MockSequence)
110105
.Setup(p => p.IsOpen)
111106
.Returns(true);
112107
SftpSessionMock.InSequence(MockSequence)
113-
.Setup(p => p.RequestRead(_handle, 0, _readBufferSize))
114-
.Returns(new byte[] {0x04});
108+
.Setup(p => p.RequestRead(_handle, 0UL, _readBufferSize))
109+
.Returns(new byte[] { 0x05, 0x04 });
115110

116111
var buffer = new byte[1];
117112

118113
var bytesRead = _target.Read(buffer, 0, buffer.Length);
119114

120115
Assert.AreEqual(buffer.Length, bytesRead);
121-
Assert.AreEqual(0x04, buffer[0]);
116+
Assert.AreEqual(0x05, buffer[0]);
117+
118+
SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(3));
119+
SftpSessionMock.Verify(p => p.RequestRead(_handle, 0UL, _readBufferSize), Times.Exactly(2));
122120
}
123121
}
124122
}
Lines changed: 22 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace Renci.SshNet.Tests.Classes.Sftp
88
{
99
[TestClass]
1010
//[Ignore]
11-
public class SftpFileStreamTest_Seek_PositionedAtMiddleOfStream_OriginBeginAndOffsetZero_WithinReadBuffer : SftpFileStreamTestBase
11+
public class SftpFileStreamTest_Seek_PositionedAtMiddleOfStream_OriginBeginAndOffsetZero_ReadBuffer : SftpFileStreamTestBase
1212
{
1313
private Random _random;
1414
private string _path;
@@ -21,7 +21,8 @@ public class SftpFileStreamTest_Seek_PositionedAtMiddleOfStream_OriginBeginAndOf
2121
private SftpFileStream _target;
2222
private long _actual;
2323
private byte[] _buffer;
24-
private byte[] _serverData;
24+
private byte[] _serverData1;
25+
private byte[] _serverData2;
2526

2627
protected override void SetupData()
2728
{
@@ -35,8 +36,9 @@ protected override void SetupData()
3536
_readBufferSize = 20;
3637
_writeBufferSize = (uint) _random.Next(5, 1000);
3738
_handle = GenerateRandom(_random.Next(1, 10), _random);
38-
_buffer = new byte[_readBufferSize - 5];
39-
_serverData = GenerateRandom((int) _readBufferSize, _random);
39+
_buffer = new byte[2]; // should be less than size of read buffer
40+
_serverData1 = GenerateRandom((int) _readBufferSize, _random);
41+
_serverData2 = GenerateRandom((int) _readBufferSize, _random);
4042
}
4143

4244
protected override void SetupMocks()
@@ -45,17 +47,17 @@ protected override void SetupMocks()
4547
.Setup(p => p.RequestOpen(_path, Flags.Read | Flags.CreateNewOrOpen, false))
4648
.Returns(_handle);
4749
SftpSessionMock.InSequence(MockSequence)
48-
.Setup(p => p.CalculateOptimalReadLength((uint)_bufferSize))
50+
.Setup(p => p.CalculateOptimalReadLength((uint) _bufferSize))
4951
.Returns(_readBufferSize);
5052
SftpSessionMock.InSequence(MockSequence)
51-
.Setup(p => p.CalculateOptimalWriteLength((uint)_bufferSize, _handle))
53+
.Setup(p => p.CalculateOptimalWriteLength((uint) _bufferSize, _handle))
5254
.Returns(_writeBufferSize);
5355
SftpSessionMock.InSequence(MockSequence)
5456
.Setup(p => p.IsOpen)
5557
.Returns(true);
5658
SftpSessionMock.InSequence(MockSequence)
5759
.Setup(p => p.RequestRead(_handle, 0UL, _readBufferSize))
58-
.Returns(_serverData);
60+
.Returns(_serverData1);
5961
SftpSessionMock.InSequence(MockSequence)
6062
.Setup(p => p.IsOpen)
6163
.Returns(true);
@@ -99,54 +101,39 @@ public void IsOpenOnSftpSessionShouldHaveBeenInvokedTwice()
99101
}
100102

101103
[TestMethod]
102-
public void ReadLessThanReadBufferSizeShouldReturnBytesFromReadBuffer()
104+
public void ReadBytesThatWereNotBufferedBeforeSeekShouldReadBytesFromServer()
103105
{
104106
SftpSessionMock.InSequence(MockSequence)
105107
.Setup(p => p.IsOpen)
106108
.Returns(true);
107-
108-
var buffer = new byte[_readBufferSize - 3];
109-
110-
var bytesRead = _target.Read(buffer, 0, buffer.Length);
111-
112-
Assert.AreEqual(buffer.Length, bytesRead);
113-
Assert.IsTrue(_serverData.Take(buffer.Length).IsEqualTo(buffer));
114-
}
115-
116-
[TestMethod]
117-
public void ReadReadBufferSizeShouldReturnBytesFromReadBuffer()
118-
{
119109
SftpSessionMock.InSequence(MockSequence)
120-
.Setup(p => p.IsOpen)
121-
.Returns(true);
110+
.Setup(p => p.RequestRead(_handle, 0UL, _readBufferSize))
111+
.Returns(_serverData2);
122112

123-
var buffer = new byte[_readBufferSize];
113+
var bytesRead = _target.Read(_buffer, 0, _buffer.Length);
124114

125-
var bytesRead = _target.Read(buffer, 0, buffer.Length);
115+
Assert.AreEqual(_buffer.Length, bytesRead);
116+
Assert.IsTrue(_serverData2.Take(_buffer.Length).IsEqualTo(_buffer));
126117

127-
Assert.AreEqual(buffer.Length, bytesRead);
128-
Assert.IsTrue(_serverData.IsEqualTo(buffer));
118+
SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(3));
119+
SftpSessionMock.Verify(p => p.RequestRead(_handle, 0UL, _readBufferSize), Times.Exactly(2));
129120
}
130121

131122
[TestMethod]
132-
public void ReadMoreThanReadBufferSizeShouldReturnBytesFromReadBufferAndReadRemaningBytesFromServer()
123+
public void ReadBytesThatWereBufferedBeforeSeekShouldReadBytesFromServer()
133124
{
134-
var serverData2 = GenerateRandom(6, _random);
135-
136125
SftpSessionMock.InSequence(MockSequence)
137126
.Setup(p => p.IsOpen)
138127
.Returns(true);
139128
SftpSessionMock.InSequence(MockSequence)
140-
.Setup(p => p.RequestRead(_handle, _readBufferSize, _readBufferSize))
141-
.Returns(serverData2);
142-
143-
var buffer = new byte[_readBufferSize + 4];
129+
.Setup(p => p.RequestRead(_handle, 0UL, _readBufferSize))
130+
.Returns(_serverData2);
144131

132+
var buffer = new byte[_buffer.Length + 1]; // we read one byte that was previously buffered
145133
var bytesRead = _target.Read(buffer, 0, buffer.Length);
146134

147135
Assert.AreEqual(buffer.Length, bytesRead);
148-
Assert.IsTrue(_serverData.Take((int) _readBufferSize).IsEqualTo(buffer.Take((int) _readBufferSize)));
149-
Assert.IsTrue(serverData2.Take(4).IsEqualTo(buffer.Take((int) _readBufferSize, 4)));
136+
Assert.IsTrue(_serverData2.Take(buffer.Length).IsEqualTo(buffer));
150137
}
151138
}
152139
}

src/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -439,8 +439,8 @@
439439
<Compile Include="Classes\Sftp\SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginBeginAndOffsetNegative.cs" />
440440
<Compile Include="Classes\Sftp\SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginBeginAndOffsetPositive.cs" />
441441
<Compile Include="Classes\Sftp\SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginBeginAndOffsetZero.cs" />
442-
<Compile Include="Classes\Sftp\SftpFileStreamTest_Seek_PositionedAtMiddleOfStream_OriginBeginAndOffsetZero_OutsideOfReadBuffer.cs" />
443-
<Compile Include="Classes\Sftp\SftpFileStreamTest_Seek_PositionedAtMiddleOfStream_OriginBeginAndOffsetZero_WithinReadBuffer.cs" />
442+
<Compile Include="Classes\Sftp\SftpFileStreamTest_Seek_PositionedAtMiddleOfStream_OriginBeginAndOffsetZero_NoBuffering.cs" />
443+
<Compile Include="Classes\Sftp\SftpFileStreamTest_Seek_PositionedAtMiddleOfStream_OriginBeginAndOffsetZero_ReadBuffer.cs" />
444444
<Compile Include="Classes\Sftp\SftpFileStreamTest_SetLength_Closed.cs" />
445445
<Compile Include="Classes\Sftp\SftpFileStreamTest_SetLength_Disposed.cs" />
446446
<Compile Include="Classes\Sftp\SftpFileStreamTest_SetLength_SessionNotOpen.cs" />

0 commit comments

Comments
 (0)