Harden and document test.

This commit is contained in:
Gert Driesen
2017-02-06 17:45:05 +01:00
parent d57dbff9ee
commit ec467689ce
@@ -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()
{