2
0

SftpFileReaderTest_LastChunkBeforeEofIsComplete.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. using System;
  2. using System.Diagnostics;
  3. using System.Threading;
  4. using Microsoft.VisualStudio.TestTools.UnitTesting;
  5. using Moq;
  6. using Renci.SshNet.Common;
  7. using Renci.SshNet.Sftp;
  8. using BufferedRead = Renci.SshNet.Sftp.SftpFileReader.BufferedRead;
  9. namespace Renci.SshNet.Tests.Classes.Sftp
  10. {
  11. [TestClass]
  12. public class SftpFileReaderTest_LastChunkBeforeEofIsComplete : SftpFileReaderTestBase
  13. {
  14. private const int ChunkLength = 32 * 1024;
  15. private MockSequence _seq;
  16. private byte[] _handle;
  17. private int _fileSize;
  18. private WaitHandle[] _waitHandleArray;
  19. private int _operationTimeout;
  20. private SftpReadAsyncResult _readAsyncResultBeyondEof;
  21. private SftpCloseAsyncResult _closeAsyncResult;
  22. private byte[] _chunk1;
  23. private byte[] _chunk2;
  24. private byte[] _chunk3;
  25. private SftpFileReader _reader;
  26. private byte[] _actualChunk1;
  27. private byte[] _actualChunk2;
  28. private byte[] _actualChunk3;
  29. protected override void SetupData()
  30. {
  31. var random = new Random();
  32. _handle = CreateByteArray(random, 5);
  33. _chunk1 = CreateByteArray(random, ChunkLength);
  34. // chunk is less than the requested length, but - together with chunk 1 - contains all data up to the EOF
  35. _chunk2 = CreateByteArray(random, ChunkLength - 10);
  36. _chunk3 = new byte[0];
  37. _fileSize = _chunk1.Length + _chunk2.Length;
  38. _waitHandleArray = new WaitHandle[2];
  39. _operationTimeout = random.Next(10000, 20000);
  40. _closeAsyncResult = new SftpCloseAsyncResult(null, null);
  41. _readAsyncResultBeyondEof = new SftpReadAsyncResult(null, null);
  42. }
  43. protected override void SetupMocks()
  44. {
  45. _seq = new MockSequence();
  46. SftpSessionMock.InSequence(_seq)
  47. .Setup(p => p.CreateWaitHandleArray(It.IsNotNull<WaitHandle>(), It.IsNotNull<WaitHandle>()))
  48. .Returns<WaitHandle, WaitHandle>((disposingWaitHandle, semaphoreAvailableWaitHandle) =>
  49. {
  50. _waitHandleArray[0] = disposingWaitHandle;
  51. _waitHandleArray[1] = semaphoreAvailableWaitHandle;
  52. return _waitHandleArray;
  53. });
  54. SftpSessionMock.InSequence(_seq).Setup(p => p.OperationTimeout).Returns(_operationTimeout);
  55. SftpSessionMock.InSequence(_seq)
  56. .Setup(p => p.WaitAny(_waitHandleArray, _operationTimeout))
  57. .Returns(() => WaitAny(_waitHandleArray, _operationTimeout));
  58. SftpSessionMock.InSequence(_seq)
  59. .Setup(p => p.BeginRead(_handle, 0, ChunkLength, It.IsNotNull<AsyncCallback>(), It.IsAny<BufferedRead>()))
  60. .Callback<byte[], ulong, uint, AsyncCallback, object>((handle, offset, length, callback, state) =>
  61. {
  62. var asyncResult = new SftpReadAsyncResult(callback, state);
  63. asyncResult.SetAsCompleted(_chunk1, false);
  64. })
  65. .Returns((SftpReadAsyncResult)null);
  66. SftpSessionMock.InSequence(_seq).Setup(p => p.OperationTimeout).Returns(_operationTimeout);
  67. SftpSessionMock.InSequence(_seq)
  68. .Setup(p => p.WaitAny(_waitHandleArray, _operationTimeout))
  69. .Returns(() => WaitAny(_waitHandleArray, _operationTimeout));
  70. SftpSessionMock.InSequence(_seq)
  71. .Setup(p => p.BeginRead(_handle, ChunkLength, ChunkLength, It.IsNotNull<AsyncCallback>(), It.IsAny<BufferedRead>()))
  72. .Callback<byte[], ulong, uint, AsyncCallback, object>((handle, offset, length, callback, state) =>
  73. {
  74. var asyncResult = new SftpReadAsyncResult(callback, state);
  75. asyncResult.SetAsCompleted(_chunk2, false);
  76. })
  77. .Returns((SftpReadAsyncResult)null);
  78. SftpSessionMock.InSequence(_seq).Setup(p => p.OperationTimeout).Returns(_operationTimeout);
  79. SftpSessionMock.InSequence(_seq)
  80. .Setup(p => p.WaitAny(_waitHandleArray, _operationTimeout))
  81. .Returns(() => WaitAny(_waitHandleArray, _operationTimeout));
  82. SftpSessionMock.InSequence(_seq)
  83. .Setup(p => p.BeginRead(_handle, 2 * ChunkLength, ChunkLength, null, It.IsAny<BufferedRead>()))
  84. .Returns(_readAsyncResultBeyondEof);
  85. SftpSessionMock.InSequence(_seq)
  86. .Setup(p => p.EndRead(_readAsyncResultBeyondEof))
  87. .Returns(_chunk3);
  88. }
  89. protected override void Arrange()
  90. {
  91. base.Arrange();
  92. _reader = new SftpFileReader(_handle, SftpSessionMock.Object, ChunkLength, 15, _fileSize);
  93. }
  94. protected override void Act()
  95. {
  96. _actualChunk1 = _reader.Read();
  97. _actualChunk2 = _reader.Read();
  98. _actualChunk3 = _reader.Read();
  99. }
  100. [TestMethod]
  101. public void FirstReadShouldReturnChunk1()
  102. {
  103. Assert.IsNotNull(_actualChunk1);
  104. Assert.AreSame(_chunk1, _actualChunk1);
  105. }
  106. [TestMethod]
  107. public void SecondReadShouldReturnChunk2()
  108. {
  109. Assert.IsNotNull(_actualChunk2);
  110. Assert.AreSame(_chunk2, _actualChunk2);
  111. }
  112. [TestMethod]
  113. public void ThirdReadShouldReturnChunk3()
  114. {
  115. Assert.IsNotNull(_actualChunk3);
  116. Assert.AreSame(_chunk3, _actualChunk3);
  117. }
  118. [TestMethod]
  119. public void ReadAfterEndOfFileShouldThrowSshException()
  120. {
  121. try
  122. {
  123. _reader.Read();
  124. Assert.Fail();
  125. }
  126. catch (SshException ex)
  127. {
  128. Assert.IsNull(ex.InnerException);
  129. Assert.AreEqual("Attempting to read beyond the end of the file.", ex.Message);
  130. }
  131. }
  132. [TestMethod]
  133. public void DisposeShouldCloseHandleAndCompleteImmediately()
  134. {
  135. SftpSessionMock.InSequence(_seq).Setup(p => p.IsOpen).Returns(true);
  136. SftpSessionMock.InSequence(_seq).Setup(p => p.BeginClose(_handle, null, null)).Returns(_closeAsyncResult);
  137. SftpSessionMock.InSequence(_seq).Setup(p => p.EndClose(_closeAsyncResult));
  138. var stopwatch = Stopwatch.StartNew();
  139. _reader.Dispose();
  140. stopwatch.Stop();
  141. Assert.IsTrue(stopwatch.ElapsedMilliseconds < 200, "Dispose took too long to complete: " + stopwatch.ElapsedMilliseconds);
  142. SftpSessionMock.Verify(p => p.IsOpen, Times.Once);
  143. SftpSessionMock.Verify(p => p.BeginClose(_handle, null, null), Times.Once);
  144. SftpSessionMock.Verify(p => p.EndClose(_closeAsyncResult), Times.Once);
  145. }
  146. }
  147. }