mirror of
https://github.com/sshnet/SSH.NET.git
synced 2026-09-11 01:36:39 +00:00
Harden and document test.
This commit is contained in:
+40
-6
@@ -10,6 +10,21 @@ using BufferedRead = Renci.SshNet.Sftp.SftpFileReader.BufferedRead;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes.Sftp
|
||||
{
|
||||
/// <summary>
|
||||
/// Runs a reader with max. 2 pending reads.
|
||||
/// The read-ahead of chunk1 starts followed by the read-ahead of chunk2.
|
||||
/// The read-ahead of chunk1 completes successfully and the resulting chunk is read.
|
||||
/// The read of this first chunk allows a third ahead-head to start.
|
||||
/// The second read-ahead uses signals to forcefully block a failure completion until the read
|
||||
/// ahead of the third chunk has completed and the semaphore is waiting for a slot to start
|
||||
/// the read-ahead of chunk4.
|
||||
/// The second read does not consume check3 as it is out of order, but instead waits for
|
||||
/// the outcome of the read-ahead of chunk2.
|
||||
///
|
||||
/// The completion with exception of chunk2 causes the second read to throw that same exception, and
|
||||
/// signals the semaphore that was waiting to start the read-ahead of chunk4. However, due to the fact
|
||||
/// that chunk2 completed with an exception, the read-ahead loop is stopped.
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class SftpFileReaderTest_ReadAheadEndInvokeException_DiscardsFurtherReadAheads : SftpFileReaderTestBase
|
||||
{
|
||||
@@ -23,7 +38,9 @@ namespace Renci.SshNet.Tests.Classes.Sftp
|
||||
private SftpCloseAsyncResult _closeAsyncResult;
|
||||
private byte[] _chunk1;
|
||||
private byte[] _chunk3;
|
||||
private ManualResetEvent _readAheadChunk2Completed;
|
||||
private ManualResetEvent _readAheadChunk3Completed;
|
||||
private ManualResetEvent _waitingForSemaphoreAfterCompletingChunk3;
|
||||
private SftpFileReader _reader;
|
||||
private SshException _exception;
|
||||
private SshException _actualException;
|
||||
@@ -35,12 +52,14 @@ namespace Renci.SshNet.Tests.Classes.Sftp
|
||||
_handle = CreateByteArray(random, 5);
|
||||
_chunk1 = CreateByteArray(random, ChunkLength);
|
||||
_chunk3 = CreateByteArray(random, ChunkLength);
|
||||
_fileSize = 3 * ChunkLength;
|
||||
_fileSize = 4 * ChunkLength;
|
||||
_waitHandleArray = new WaitHandle[2];
|
||||
_operationTimeout = random.Next(10000, 20000);
|
||||
_closeAsyncResult = new SftpCloseAsyncResult(null, null);
|
||||
|
||||
_readAheadChunk2Completed = new ManualResetEvent(false);
|
||||
_readAheadChunk3Completed = new ManualResetEvent(false);
|
||||
_waitingForSemaphoreAfterCompletingChunk3 = new ManualResetEvent(false);
|
||||
|
||||
_exception = new SshException();
|
||||
}
|
||||
@@ -79,12 +98,16 @@ namespace Renci.SshNet.Tests.Classes.Sftp
|
||||
{
|
||||
ThreadAbstraction.ExecuteThread(() =>
|
||||
{
|
||||
// wait until the read-ahead for chunk3 has completed
|
||||
_readAheadChunk3Completed.WaitOne(TimeSpan.FromSeconds(5));
|
||||
|
||||
// wait until the read-ahead for chunk3 has completed; this should allow
|
||||
// the read-ahead of chunk4 to start
|
||||
_readAheadChunk3Completed.WaitOne(TimeSpan.FromSeconds(3));
|
||||
// wait until the semaphore wait to start with chunk4 has started
|
||||
_waitingForSemaphoreAfterCompletingChunk3.WaitOne(TimeSpan.FromSeconds(7));
|
||||
// complete async read of chunk2 with exception
|
||||
var asyncResult = new SftpReadAsyncResult(callback, state);
|
||||
asyncResult.SetAsCompleted(_exception, false);
|
||||
// signal that read-ahead of chunk 2 has completed
|
||||
_readAheadChunk2Completed.Set();
|
||||
});
|
||||
})
|
||||
.Returns((SftpReadAsyncResult)null);
|
||||
@@ -98,11 +121,16 @@ namespace Renci.SshNet.Tests.Classes.Sftp
|
||||
{
|
||||
var asyncResult = new SftpReadAsyncResult(callback, state);
|
||||
asyncResult.SetAsCompleted(_chunk3, false);
|
||||
|
||||
// signal that we've completed the read-ahead for chunk3
|
||||
_readAheadChunk3Completed.Set();
|
||||
})
|
||||
.Returns((SftpReadAsyncResult)null);
|
||||
SftpSessionMock.InSequence(_seq).Setup(p => p.OperationTimeout).Returns(_operationTimeout);
|
||||
SftpSessionMock.InSequence(_seq)
|
||||
.Setup(p => p.WaitAny(_waitHandleArray, _operationTimeout))
|
||||
.Callback(() => _waitingForSemaphoreAfterCompletingChunk3.Set())
|
||||
.Returns(() => WaitAny(_waitHandleArray, _operationTimeout));
|
||||
|
||||
}
|
||||
|
||||
protected override void Arrange()
|
||||
@@ -135,7 +163,7 @@ namespace Renci.SshNet.Tests.Classes.Sftp
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ReahAheadOfChunk3ShouldHaveBeenDone()
|
||||
public void ReahAheadOfChunk3ShouldHaveStarted()
|
||||
{
|
||||
SftpSessionMock.Verify(p => p.BeginRead(_handle, 2 * ChunkLength, ChunkLength, It.IsNotNull<AsyncCallback>(), It.IsAny<BufferedRead>()), Times.Once);
|
||||
}
|
||||
@@ -154,6 +182,12 @@ namespace Renci.SshNet.Tests.Classes.Sftp
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void WaitAnyOFSftpSessionShouldHaveBeenInvokedFourTimes()
|
||||
{
|
||||
SftpSessionMock.Verify(p => p.WaitAny(_waitHandleArray, _operationTimeout), Times.Exactly(4));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DisposeShouldCloseHandleAndCompleteImmediately()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user