SftpFileStreamTest_WriteAsync_SessionOpen_CountGreatherThanTwoTimesTheWriteBufferSize.cs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. #if FEATURE_TAP
  2. using System;
  3. using System.Globalization;
  4. using System.IO;
  5. using System.Threading;
  6. using System.Threading.Tasks;
  7. using Microsoft.VisualStudio.TestTools.UnitTesting;
  8. using Moq;
  9. using Renci.SshNet.Common;
  10. using Renci.SshNet.Sftp;
  11. using Renci.SshNet.Sftp.Responses;
  12. namespace Renci.SshNet.Tests.Classes.Sftp
  13. {
  14. [TestClass]
  15. public class SftpFileStreamTest_WriteAsync_SessionOpen_CountGreatherThanTwoTimesTheWriteBufferSize : SftpFileStreamAsyncTestBase
  16. {
  17. private SftpFileStream _target;
  18. private string _path;
  19. private byte[] _handle;
  20. private uint _bufferSize;
  21. private uint _readBufferSize;
  22. private uint _writeBufferSize;
  23. private byte[] _data;
  24. private int _count;
  25. private int _offset;
  26. private Random _random;
  27. private uint _expectedWrittenByteCount;
  28. private int _expectedBufferedByteCount;
  29. private byte[] _expectedBufferedBytes;
  30. private CancellationToken _cancellationToken;
  31. protected override void SetupData()
  32. {
  33. base.SetupData();
  34. _random = new Random();
  35. _path = _random.Next().ToString(CultureInfo.InvariantCulture);
  36. _handle = GenerateRandom(5, _random);
  37. _bufferSize = (uint)_random.Next(1, 1000);
  38. _readBufferSize = (uint) _random.Next(0, 1000);
  39. _writeBufferSize = (uint) _random.Next(500, 1000);
  40. _data = new byte[(_writeBufferSize * 2) + 15];
  41. _random.NextBytes(_data);
  42. _offset = _random.Next(1, 5);
  43. // to get multiple SSH_FXP_WRITE messages (and verify the offset is updated correctly), we make sure
  44. // the number of bytes to write is at least two times the write buffer size; we write a few extra bytes to
  45. // ensure the buffer is not empty after the writes so we can verify whether Length, Dispose and Flush
  46. // flush the buffer
  47. _count = ((int) _writeBufferSize * 2) + _random.Next(1, 5);
  48. _expectedWrittenByteCount = (2 * _writeBufferSize);
  49. _expectedBufferedByteCount = (int)(_count - _expectedWrittenByteCount);
  50. _expectedBufferedBytes = _data.Take(_offset + (int)_expectedWrittenByteCount, _expectedBufferedByteCount);
  51. _cancellationToken = new CancellationToken();
  52. }
  53. protected override void SetupMocks()
  54. {
  55. SftpSessionMock.InSequence(MockSequence)
  56. .Setup(p => p.RequestOpenAsync(_path, Flags.Write | Flags.CreateNewOrOpen | Flags.Truncate, _cancellationToken))
  57. .ReturnsAsync(_handle);
  58. SftpSessionMock.InSequence(MockSequence)
  59. .Setup(p => p.CalculateOptimalReadLength(_bufferSize))
  60. .Returns(_readBufferSize);
  61. SftpSessionMock.InSequence(MockSequence)
  62. .Setup(p => p.CalculateOptimalWriteLength(_bufferSize, _handle))
  63. .Returns(_writeBufferSize);
  64. SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true);
  65. SftpSessionMock.InSequence(MockSequence)
  66. .Setup(p => p.RequestWriteAsync(_handle, 0, _data, _offset, (int)_writeBufferSize, _cancellationToken))
  67. .Returns(Task.CompletedTask);
  68. SftpSessionMock.InSequence(MockSequence)
  69. .Setup(p => p.RequestWriteAsync(_handle, _writeBufferSize, _data, _offset + (int)_writeBufferSize, (int)_writeBufferSize, _cancellationToken))
  70. .Returns(Task.CompletedTask);
  71. }
  72. [TestCleanup]
  73. public void TearDown()
  74. {
  75. if (SftpSessionMock != null)
  76. {
  77. // allow Dispose to complete successfully
  78. SftpSessionMock.InSequence(MockSequence)
  79. .Setup(p => p.IsOpen)
  80. .Returns(true);
  81. SftpSessionMock.InSequence(MockSequence)
  82. .Setup(p => p.RequestWriteAsync(_handle, _expectedWrittenByteCount, It.IsAny<byte[]>(), 0, _expectedBufferedByteCount, _cancellationToken))
  83. .Returns(Task.CompletedTask);
  84. SftpSessionMock.InSequence(MockSequence)
  85. .Setup(p => p.RequestClose(_handle));
  86. }
  87. }
  88. protected override async Task ArrangeAsync()
  89. {
  90. await base.ArrangeAsync();
  91. _target = await SftpFileStream.OpenAsync(SftpSessionMock.Object, _path, FileMode.Create, FileAccess.Write, (int) _bufferSize, _cancellationToken);
  92. }
  93. protected override Task ActAsync()
  94. {
  95. return _target.WriteAsync(_data, _offset, _count);
  96. }
  97. [TestMethod]
  98. public void RequestWriteOnSftpSessionShouldBeInvokedTwice()
  99. {
  100. SftpSessionMock.Verify(p => p.RequestWriteAsync(_handle, 0, _data, _offset, (int)_writeBufferSize, _cancellationToken), Times.Once);
  101. SftpSessionMock.Verify(p => p.RequestWriteAsync(_handle, _writeBufferSize, _data, _offset + (int)_writeBufferSize, (int)_writeBufferSize, _cancellationToken), Times.Once);
  102. }
  103. [TestMethod]
  104. public void PositionShouldBeNumberOfBytesWrittenToFileAndNUmberOfBytesInBuffer()
  105. {
  106. SftpSessionMock.InSequence(MockSequence).Setup(p => p.IsOpen).Returns(true);
  107. Assert.AreEqual(_count, _target.Position);
  108. }
  109. [TestMethod]
  110. public async Task FlushShouldFlushBuffer()
  111. {
  112. byte[] actualFlushedData = null;
  113. SftpSessionMock.InSequence(MockSequence)
  114. .Setup(p => p.IsOpen)
  115. .Returns(true);
  116. SftpSessionMock.InSequence(MockSequence)
  117. .Setup(p => p.RequestWriteAsync(_handle, _expectedWrittenByteCount, It.IsAny<byte[]>(), 0, _expectedBufferedByteCount, _cancellationToken))
  118. .Callback<byte[], ulong, byte[], int, int, CancellationToken>((handle, serverFileOffset, data, offset, length, ct) => actualFlushedData = data.Take(offset, length))
  119. .Returns(Task.CompletedTask);
  120. await _target.FlushAsync();
  121. Assert.IsTrue(actualFlushedData.IsEqualTo(_expectedBufferedBytes));
  122. SftpSessionMock.Verify(p => p.RequestWriteAsync(_handle, _expectedWrittenByteCount, It.IsAny<byte[]>(), 0, _expectedBufferedByteCount, _cancellationToken), Times.Once);
  123. }
  124. }
  125. }
  126. #endif