|
|
@@ -17,7 +17,9 @@ namespace Renci.SshNet.Tests.Classes.Sftp
|
|
|
private MockSequence _seq;
|
|
|
private byte[] _handle;
|
|
|
private int _fileSize;
|
|
|
+ private WaitHandle[] _waitHandleArray;
|
|
|
private int _operationTimeout;
|
|
|
+ private SftpCloseAsyncResult _closeAsyncResult;
|
|
|
private byte[] _chunk1;
|
|
|
private byte[] _chunk2;
|
|
|
private byte[] _chunk2CatchUp1;
|
|
|
@@ -34,6 +36,7 @@ namespace Renci.SshNet.Tests.Classes.Sftp
|
|
|
private ManualResetEvent _chunk3BeginRead;
|
|
|
private ManualResetEvent _chunk4BeginRead;
|
|
|
private ManualResetEvent _chunk5BeginRead;
|
|
|
+ private ManualResetEvent _waitBeforeChunk6;
|
|
|
private ManualResetEvent _chunk6BeginRead;
|
|
|
private byte[] _actualChunk4;
|
|
|
private byte[] _actualChunk2CatchUp1;
|
|
|
@@ -60,18 +63,30 @@ namespace Renci.SshNet.Tests.Classes.Sftp
|
|
|
_chunk3BeginRead = new ManualResetEvent(false);
|
|
|
_chunk4BeginRead = new ManualResetEvent(false);
|
|
|
_chunk5BeginRead = new ManualResetEvent(false);
|
|
|
+ _waitBeforeChunk6 = new ManualResetEvent(false);
|
|
|
_chunk6BeginRead = new ManualResetEvent(false);
|
|
|
_fileSize = _chunk1.Length + _chunk2.Length + _chunk2CatchUp1.Length + _chunk2CatchUp2.Length + _chunk3.Length + _chunk4.Length + _chunk5.Length;
|
|
|
- _operationTimeout = random.Next();
|
|
|
+ _waitHandleArray = new WaitHandle[2];
|
|
|
+ _operationTimeout = random.Next(10000, 20000);
|
|
|
+ _closeAsyncResult = new SftpCloseAsyncResult(null, null);
|
|
|
}
|
|
|
|
|
|
protected override void SetupMocks()
|
|
|
{
|
|
|
_seq = new MockSequence();
|
|
|
|
|
|
+ SftpSessionMock.InSequence(_seq)
|
|
|
+ .Setup(p => p.CreateWaitHandleArray(It.IsNotNull<WaitHandle>(), It.IsNotNull<WaitHandle>()))
|
|
|
+ .Returns<WaitHandle, WaitHandle>((disposingWaitHandle, semaphoreAvailableWaitHandle) =>
|
|
|
+ {
|
|
|
+ _waitHandleArray[0] = disposingWaitHandle;
|
|
|
+ _waitHandleArray[1] = semaphoreAvailableWaitHandle;
|
|
|
+ return _waitHandleArray;
|
|
|
+ });
|
|
|
SftpSessionMock.InSequence(_seq).Setup(p => p.OperationTimeout).Returns(_operationTimeout);
|
|
|
SftpSessionMock.InSequence(_seq)
|
|
|
- .Setup(p => p.WaitOnHandle(It.IsAny<WaitHandle>(), _operationTimeout));
|
|
|
+ .Setup(p => p.WaitAny(_waitHandleArray, _operationTimeout))
|
|
|
+ .Returns(() => WaitAny(_waitHandleArray, _operationTimeout));
|
|
|
SftpSessionMock.InSequence(_seq)
|
|
|
.Setup(p => p.BeginRead(_handle, 0, ChunkLength, It.IsNotNull<AsyncCallback>(), It.IsAny<BufferedRead>()))
|
|
|
.Callback<byte[], ulong, uint, AsyncCallback, object>((handle, offset, length, callback, state) =>
|
|
|
@@ -83,7 +98,8 @@ namespace Renci.SshNet.Tests.Classes.Sftp
|
|
|
.Returns((SftpReadAsyncResult)null);
|
|
|
SftpSessionMock.InSequence(_seq).Setup(p => p.OperationTimeout).Returns(_operationTimeout);
|
|
|
SftpSessionMock.InSequence(_seq)
|
|
|
- .Setup(p => p.WaitOnHandle(It.IsAny<WaitHandle>(), _operationTimeout));
|
|
|
+ .Setup(p => p.WaitAny(_waitHandleArray, _operationTimeout))
|
|
|
+ .Returns(() => WaitAny(_waitHandleArray, _operationTimeout));
|
|
|
SftpSessionMock.InSequence(_seq)
|
|
|
.Setup(p => p.BeginRead(_handle, ChunkLength, ChunkLength, It.IsNotNull<AsyncCallback>(), It.IsAny<BufferedRead>()))
|
|
|
.Callback<byte[], ulong, uint, AsyncCallback, object>((handle, offset, length, callback, state) =>
|
|
|
@@ -95,7 +111,8 @@ namespace Renci.SshNet.Tests.Classes.Sftp
|
|
|
.Returns((SftpReadAsyncResult)null);
|
|
|
SftpSessionMock.InSequence(_seq).Setup(p => p.OperationTimeout).Returns(_operationTimeout);
|
|
|
SftpSessionMock.InSequence(_seq)
|
|
|
- .Setup(p => p.WaitOnHandle(It.IsAny<WaitHandle>(), _operationTimeout));
|
|
|
+ .Setup(p => p.WaitAny(_waitHandleArray, _operationTimeout))
|
|
|
+ .Returns(() => WaitAny(_waitHandleArray, _operationTimeout));
|
|
|
SftpSessionMock.InSequence(_seq)
|
|
|
.Setup(p => p.BeginRead(_handle, 2 * ChunkLength, ChunkLength, It.IsNotNull<AsyncCallback>(), It.IsAny<BufferedRead>()))
|
|
|
.Callback<byte[], ulong, uint, AsyncCallback, object>((handle, offset, length, callback, state) =>
|
|
|
@@ -107,7 +124,8 @@ namespace Renci.SshNet.Tests.Classes.Sftp
|
|
|
.Returns((SftpReadAsyncResult)null);
|
|
|
SftpSessionMock.InSequence(_seq).Setup(p => p.OperationTimeout).Returns(_operationTimeout);
|
|
|
SftpSessionMock.InSequence(_seq)
|
|
|
- .Setup(p => p.WaitOnHandle(It.IsAny<WaitHandle>(), _operationTimeout));
|
|
|
+ .Setup(p => p.WaitAny(_waitHandleArray, _operationTimeout))
|
|
|
+ .Returns(() => WaitAny(_waitHandleArray, _operationTimeout));
|
|
|
SftpSessionMock.InSequence(_seq)
|
|
|
.Setup(p => p.BeginRead(_handle, 3 * ChunkLength, ChunkLength, It.IsNotNull<AsyncCallback>(), It.IsAny<BufferedRead>()))
|
|
|
.Callback<byte[], ulong, uint, AsyncCallback, object>((handle, offset, length, callback, state) =>
|
|
|
@@ -119,7 +137,8 @@ namespace Renci.SshNet.Tests.Classes.Sftp
|
|
|
.Returns((SftpReadAsyncResult)null);
|
|
|
SftpSessionMock.InSequence(_seq).Setup(p => p.OperationTimeout).Returns(_operationTimeout);
|
|
|
SftpSessionMock.InSequence(_seq)
|
|
|
- .Setup(p => p.WaitOnHandle(It.IsAny<WaitHandle>(), _operationTimeout));
|
|
|
+ .Setup(p => p.WaitAny(_waitHandleArray, _operationTimeout))
|
|
|
+ .Returns(() => WaitAny(_waitHandleArray, _operationTimeout));
|
|
|
SftpSessionMock.InSequence(_seq)
|
|
|
.Setup(p => p.BeginRead(_handle, 4 * ChunkLength, ChunkLength, It.IsNotNull<AsyncCallback>(), It.IsAny<BufferedRead>()))
|
|
|
.Callback<byte[], ulong, uint, AsyncCallback, object>((handle, offset, length, callback, state) =>
|
|
|
@@ -129,15 +148,17 @@ namespace Renci.SshNet.Tests.Classes.Sftp
|
|
|
asyncResult.SetAsCompleted(_chunk5, false);
|
|
|
})
|
|
|
.Returns((SftpReadAsyncResult)null);
|
|
|
+ SftpSessionMock.InSequence(_seq).Setup(p => p.OperationTimeout).Returns(_operationTimeout);
|
|
|
+ SftpSessionMock.InSequence(_seq)
|
|
|
+ .Setup(p => p.WaitAny(_waitHandleArray, _operationTimeout))
|
|
|
+ .Callback(() => _waitBeforeChunk6.Set())
|
|
|
+ .Returns(() => WaitAny(_waitHandleArray, _operationTimeout));
|
|
|
SftpSessionMock.InSequence(_seq)
|
|
|
.Setup(p => p.RequestRead(_handle, 2 * ChunkLength - 17, 17))
|
|
|
.Returns(_chunk2CatchUp1);
|
|
|
SftpSessionMock.InSequence(_seq)
|
|
|
.Setup(p => p.RequestRead(_handle, 2 * ChunkLength - 7, 7))
|
|
|
.Returns(_chunk2CatchUp2);
|
|
|
- SftpSessionMock.InSequence(_seq).Setup(p => p.OperationTimeout).Returns(_operationTimeout);
|
|
|
- SftpSessionMock.InSequence(_seq)
|
|
|
- .Setup(p => p.WaitOnHandle(It.IsAny<WaitHandle>(), _operationTimeout));
|
|
|
SftpSessionMock.InSequence(_seq)
|
|
|
.Setup(p => p.BeginRead(_handle, 5 * ChunkLength, ChunkLength, It.IsNotNull<AsyncCallback>(), It.IsAny<BufferedRead>()))
|
|
|
.Callback<byte[], ulong, uint, AsyncCallback, object>((handle, offset, length, callback, state) =>
|
|
|
@@ -170,6 +191,8 @@ namespace Renci.SshNet.Tests.Classes.Sftp
|
|
|
_actualChunk2 = _reader.Read();
|
|
|
// consuming chunk2 allows chunk5 to be read-ahead
|
|
|
Assert.IsTrue(_chunk5BeginRead.WaitOne(200));
|
|
|
+ // pauze until the read-ahead has started waiting a semaphore to become available
|
|
|
+ Assert.IsTrue(_waitBeforeChunk6.WaitOne(200));
|
|
|
// consume remaining parts of chunk 2
|
|
|
_actualChunk2CatchUp1 = _reader.Read();
|
|
|
_actualChunk2CatchUp2 = _reader.Read();
|
|
|
@@ -261,7 +284,8 @@ namespace Renci.SshNet.Tests.Classes.Sftp
|
|
|
[TestMethod]
|
|
|
public void DisposeShouldCloseHandleAndCompleteImmediately()
|
|
|
{
|
|
|
- SftpSessionMock.InSequence(_seq).Setup(p => p.RequestClose(_handle));
|
|
|
+ SftpSessionMock.InSequence(_seq).Setup(p => p.BeginClose(_handle, null, null)).Returns(_closeAsyncResult);
|
|
|
+ SftpSessionMock.InSequence(_seq).Setup(p => p.EndClose(_closeAsyncResult));
|
|
|
|
|
|
var stopwatch = Stopwatch.StartNew();
|
|
|
_reader.Dispose();
|
|
|
@@ -269,7 +293,8 @@ namespace Renci.SshNet.Tests.Classes.Sftp
|
|
|
|
|
|
Assert.IsTrue(stopwatch.ElapsedMilliseconds < 200, "Dispose took too long to complete: " + stopwatch.ElapsedMilliseconds);
|
|
|
|
|
|
- SftpSessionMock.Verify(p => p.RequestClose(_handle), Times.Once);
|
|
|
+ SftpSessionMock.Verify(p => p.BeginClose(_handle, null, null), Times.Once);
|
|
|
+ SftpSessionMock.Verify(p => p.EndClose(_closeAsyncResult), Times.Once);
|
|
|
}
|
|
|
}
|
|
|
}
|