SftpSessionTest_Connected_RequestRead.cs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Runtime.InteropServices;
  5. using System.Text;
  6. using Microsoft.VisualStudio.TestTools.UnitTesting;
  7. using Moq;
  8. using Renci.SshNet.Channels;
  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 SftpSessionTest_Connected_RequestRead
  16. {
  17. private Mock<ISession> _sessionMock;
  18. private Mock<IChannelSession> _channelSessionMock;
  19. private SftpSession _sftpSession;
  20. private TimeSpan _operationTimeout;
  21. private byte[] _actual;
  22. private byte[] _expected;
  23. private Encoding _encoding;
  24. [TestInitialize]
  25. public void Setup()
  26. {
  27. Arrange();
  28. Act();
  29. }
  30. protected void Arrange()
  31. {
  32. var random = new Random();
  33. _operationTimeout = TimeSpan.FromMilliseconds(random.Next(100, 500));
  34. _expected = new byte[random.Next(30, 50)];
  35. _encoding = Encoding.UTF8;
  36. random.NextBytes(_expected);
  37. _sessionMock = new Mock<ISession>(MockBehavior.Strict);
  38. _channelSessionMock = new Mock<IChannelSession>(MockBehavior.Strict);
  39. var sequence = new MockSequence();
  40. _sessionMock.InSequence(sequence).Setup(p => p.CreateChannelSession()).Returns(_channelSessionMock.Object);
  41. _channelSessionMock.InSequence(sequence).Setup(p => p.Open());
  42. _channelSessionMock.InSequence(sequence).Setup(p => p.SendSubsystemRequest("sftp")).Returns(true);
  43. _channelSessionMock.InSequence(sequence).Setup(p => p.IsOpen).Returns(true);
  44. _channelSessionMock.InSequence(sequence).Setup(p => p.SendData(It.IsAny<byte[]>())).Callback(
  45. () =>
  46. {
  47. // generate response for SftpInitRequest
  48. var versionInfoResponse = SftpVersionResponseBuilder.Create(3)
  49. .Build();
  50. _channelSessionMock.Raise(
  51. c => c.DataReceived += null,
  52. new ChannelDataEventArgs(0, versionInfoResponse));
  53. });
  54. _channelSessionMock.InSequence(sequence).Setup(p => p.IsOpen).Returns(true);
  55. _channelSessionMock.InSequence(sequence).Setup(p => p.SendData(It.IsAny<byte[]>())).Callback(
  56. () =>
  57. {
  58. var sftpNameResponse = CreateSftpNameResponse(1, _encoding, "ABC");
  59. _channelSessionMock.Raise(
  60. c => c.DataReceived += null,
  61. new ChannelDataEventArgs(0, sftpNameResponse));
  62. }
  63. );
  64. _channelSessionMock.InSequence(sequence).Setup(p => p.IsOpen).Returns(true);
  65. _channelSessionMock.InSequence(sequence).Setup(p => p.SendData(It.IsAny<byte[]>())).Callback(
  66. () =>
  67. {
  68. var sftpDataResponse = CreateSftpDataResponse(2, _expected);
  69. _channelSessionMock.Raise(
  70. c => c.DataReceived += null,
  71. new ChannelDataEventArgs(0, sftpDataResponse.Take(0, 20)));
  72. _channelSessionMock.Raise(
  73. c => c.DataReceived += null,
  74. new ChannelDataEventArgs(0, sftpDataResponse.Take(20, sftpDataResponse.Length - 20)));
  75. }
  76. );
  77. _sftpSession = new SftpSession(_sessionMock.Object, _operationTimeout, _encoding);
  78. _sftpSession.Connect();
  79. }
  80. protected void Act()
  81. {
  82. _actual = _sftpSession.RequestRead(new byte[0], 0, 200);
  83. }
  84. [TestMethod]
  85. public void ReturnedValueShouldBeDataOfSftpDataResponse()
  86. {
  87. Assert.IsNotNull(_actual);
  88. Assert.IsTrue(_expected.SequenceEqual(_actual));
  89. }
  90. private static byte[] CreateSftpDataResponse(uint responseId, byte[] data)
  91. {
  92. var sshDataStream = new SshDataStream(4 + 1 + 4 + 4 + data.Length + 1);
  93. sshDataStream.Write((uint) sshDataStream.Capacity - 4);
  94. sshDataStream.WriteByte((byte) SftpMessageTypes.Data);
  95. sshDataStream.Write(responseId);
  96. sshDataStream.Write((uint) data.Length);
  97. sshDataStream.Write(data, 0, data.Length);
  98. sshDataStream.WriteByte(1); // EOF
  99. return sshDataStream.ToArray();
  100. }
  101. private static byte[] CreateSftpNameResponse(uint responseId, Encoding encoding, params string[] names)
  102. {
  103. var namesAndAttributes = new List<byte>();
  104. foreach (var name in names)
  105. {
  106. var nameBytes = encoding.GetBytes(name);
  107. var attributesBytes = SftpFileAttributes.Empty.GetBytes();
  108. namesAndAttributes.AddRange((((uint) nameBytes.Length).GetBytes())); // filename length
  109. namesAndAttributes.AddRange(nameBytes); // filename
  110. namesAndAttributes.AddRange(((uint) 0).GetBytes()); // longname length
  111. namesAndAttributes.AddRange(attributesBytes); // attributes
  112. }
  113. var namesAndAttributesBytes = namesAndAttributes.ToArray();
  114. var sshDataStream = new SshDataStream(4 + 1 + 4 + 4 + namesAndAttributesBytes.Length);
  115. sshDataStream.Write((uint) sshDataStream.Capacity - 4);
  116. sshDataStream.WriteByte((byte) SftpMessageTypes.Name);
  117. sshDataStream.Write(responseId);
  118. sshDataStream.Write((uint) names.Length);
  119. sshDataStream.Write(namesAndAttributesBytes, 0, namesAndAttributesBytes.Length);
  120. return sshDataStream.ToArray();
  121. }
  122. }
  123. }