SftpFileReaderTest_Dispose_SftpSessionIsOpen_BeginCloseThrowsException.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. using System;
  2. using System.Threading;
  3. using Microsoft.VisualStudio.TestTools.UnitTesting;
  4. using Moq;
  5. using Renci.SshNet.Common;
  6. using Renci.SshNet.Sftp;
  7. using BufferedRead = Renci.SshNet.Sftp.SftpFileReader.BufferedRead;
  8. namespace Renci.SshNet.Tests.Classes.Sftp
  9. {
  10. [TestClass]
  11. public class SftpFileReaderTest_Dispose_SftpSessionIsOpen_BeginCloseThrowsException : SftpFileReaderTestBase
  12. {
  13. private const int ChunkLength = 32 * 1024;
  14. private MockSequence _seq;
  15. private byte[] _handle;
  16. private int _fileSize;
  17. private WaitHandle[] _waitHandleArray;
  18. private int _operationTimeout;
  19. private SftpFileReader _reader;
  20. private AsyncCallback _readAsyncCallback;
  21. private ManualResetEvent _beginReadInvoked;
  22. private EventWaitHandle _disposeCompleted;
  23. [TestCleanup]
  24. public void TearDown()
  25. {
  26. _beginReadInvoked?.Dispose();
  27. _disposeCompleted?.Dispose();
  28. }
  29. protected override void SetupData()
  30. {
  31. var random = new Random();
  32. _handle = CreateByteArray(random, 5);
  33. _fileSize = 5000;
  34. _waitHandleArray = new WaitHandle[2];
  35. _operationTimeout = random.Next(10000, 20000);
  36. _beginReadInvoked = new ManualResetEvent(false);
  37. _disposeCompleted = new ManualResetEvent(false);
  38. _readAsyncCallback = null;
  39. }
  40. protected override void SetupMocks()
  41. {
  42. _seq = new MockSequence();
  43. _ = SftpSessionMock.InSequence(_seq)
  44. .Setup(p => p.CreateWaitHandleArray(It.IsNotNull<WaitHandle>(), It.IsNotNull<WaitHandle>()))
  45. .Returns<WaitHandle, WaitHandle>((disposingWaitHandle, semaphoreAvailableWaitHandle) =>
  46. {
  47. _waitHandleArray[0] = disposingWaitHandle;
  48. _waitHandleArray[1] = semaphoreAvailableWaitHandle;
  49. return _waitHandleArray;
  50. });
  51. _ = SftpSessionMock.InSequence(_seq)
  52. .Setup(p => p.OperationTimeout)
  53. .Returns(_operationTimeout);
  54. _ = SftpSessionMock.InSequence(_seq)
  55. .Setup(p => p.WaitAny(_waitHandleArray, _operationTimeout))
  56. .Returns(() => WaitAny(_waitHandleArray, _operationTimeout));
  57. _ = SftpSessionMock.InSequence(_seq)
  58. .Setup(p => p.BeginRead(_handle, 0, ChunkLength, It.IsNotNull<AsyncCallback>(), It.IsAny<BufferedRead>()))
  59. .Callback(() =>
  60. {
  61. // harden test by making sure that we've invoked BeginRead before Dispose is invoked
  62. _ = _beginReadInvoked.Set();
  63. })
  64. .Returns<byte[], ulong, uint, AsyncCallback, object>((handle, offset, length, callback, state) =>
  65. {
  66. _readAsyncCallback = callback;
  67. return null;
  68. })
  69. .Callback(() =>
  70. {
  71. // wait until Dispose has been invoked on reader to allow us to harden test, and
  72. // verify whether Dispose will prevent us from entering the read-ahead loop again
  73. _ = _waitHandleArray[0].WaitOne();
  74. });
  75. _ = SftpSessionMock.InSequence(_seq)
  76. .Setup(p => p.IsOpen)
  77. .Returns(true);
  78. _ = SftpSessionMock.InSequence(_seq)
  79. .Setup(p => p.BeginClose(_handle, null, null))
  80. .Throws(new SshException());
  81. }
  82. protected override void Arrange()
  83. {
  84. base.Arrange();
  85. _reader = new SftpFileReader(_handle, SftpSessionMock.Object, ChunkLength, 1, _fileSize);
  86. }
  87. protected override void Act()
  88. {
  89. Assert.IsTrue(_beginReadInvoked.WaitOne(5000));
  90. _reader.Dispose();
  91. }
  92. [TestMethod]
  93. public void ReadAfterDisposeShouldThrowObjectDisposedException()
  94. {
  95. try
  96. {
  97. _ = _reader.Read();
  98. Assert.Fail();
  99. }
  100. catch (ObjectDisposedException ex)
  101. {
  102. Assert.IsNull(ex.InnerException);
  103. Assert.AreEqual(typeof(SftpFileReader).FullName, ex.ObjectName);
  104. }
  105. }
  106. [TestMethod]
  107. public void InvokeOfReadAheadCallbackShouldCompleteImmediately()
  108. {
  109. Assert.IsNotNull(_readAsyncCallback);
  110. _readAsyncCallback(new SftpReadAsyncResult(null, null));
  111. }
  112. [TestMethod]
  113. public void BeginCloseOnSftpSessionShouldHaveBeenInvokedOnce()
  114. {
  115. SftpSessionMock.Verify(p => p.BeginClose(_handle, null, null), Times.Once);
  116. }
  117. }
  118. }