ScpClientTest_Upload_FileInfoAndPath_Success.cs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Text;
  7. using Microsoft.VisualStudio.TestTools.UnitTesting;
  8. using Moq;
  9. using Renci.SshNet.Channels;
  10. using Renci.SshNet.Common;
  11. namespace Renci.SshNet.Tests.Classes
  12. {
  13. [TestClass]
  14. public class ScpClientTest_Upload_FileInfoAndPath_Success
  15. {
  16. private Mock<IServiceFactory> _serviceFactoryMock;
  17. private Mock<ISession> _sessionMock;
  18. private Mock<IChannelSession> _channelSessionMock;
  19. private Mock<PipeStream> _pipeStreamMock;
  20. private ConnectionInfo _connectionInfo;
  21. private ScpClient _scpClient;
  22. private FileInfo _fileInfo;
  23. private string _path;
  24. private int _bufferSize;
  25. private byte[] _fileContent;
  26. private string _fileName;
  27. private int _fileSize;
  28. private IList<ScpUploadEventArgs> _uploadingRegister;
  29. [TestInitialize]
  30. public void Setup()
  31. {
  32. Arrange();
  33. Act();
  34. }
  35. [TestCleanup]
  36. public void Cleanup()
  37. {
  38. if (_fileName != null)
  39. {
  40. File.Delete(_fileName);
  41. _fileName = null;
  42. }
  43. }
  44. protected void Arrange()
  45. {
  46. var random = new Random();
  47. _bufferSize = random.Next(5, 15);
  48. _fileSize = _bufferSize + 2; //force uploading 2 chunks
  49. _fileContent = CreateContent(_fileSize);
  50. _fileName = CreateTemporaryFile(_fileContent);
  51. _connectionInfo = new ConnectionInfo("host", 22, "user", new PasswordAuthenticationMethod("user", "pwd"));
  52. _fileInfo = new FileInfo(_fileName);
  53. _path = random.Next().ToString(CultureInfo.InvariantCulture);
  54. _uploadingRegister = new List<ScpUploadEventArgs>();
  55. _serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
  56. _sessionMock = new Mock<ISession>(MockBehavior.Strict);
  57. _channelSessionMock = new Mock<IChannelSession>(MockBehavior.Strict);
  58. _pipeStreamMock = new Mock<PipeStream>(MockBehavior.Strict);
  59. var sequence = new MockSequence();
  60. _serviceFactoryMock.InSequence(sequence)
  61. .Setup(p => p.CreateSession(_connectionInfo))
  62. .Returns(_sessionMock.Object);
  63. _sessionMock.InSequence(sequence).Setup(p => p.Connect());
  64. _serviceFactoryMock.InSequence(sequence).Setup(p => p.CreatePipeStream()).Returns(_pipeStreamMock.Object);
  65. _sessionMock.InSequence(sequence).Setup(p => p.CreateChannelSession()).Returns(_channelSessionMock.Object);
  66. _channelSessionMock.InSequence(sequence).Setup(p => p.Open());
  67. _channelSessionMock.InSequence(sequence)
  68. .Setup(
  69. p => p.SendExecRequest(string.Format("scp -t \"{0}\"", _path))).Returns(true);
  70. for (var i = 0; i < random.Next(1, 3); i++)
  71. _pipeStreamMock.InSequence(sequence).Setup(p => p.ReadByte()).Returns(-1);
  72. _pipeStreamMock.InSequence(sequence).Setup(p => p.ReadByte()).Returns(0);
  73. _channelSessionMock.InSequence(sequence).Setup(p => p.SendData(It.IsAny<byte[]>()));
  74. for (var i = 0; i < random.Next(1, 3); i++)
  75. _pipeStreamMock.InSequence(sequence).Setup(p => p.ReadByte()).Returns(-1);
  76. _pipeStreamMock.InSequence(sequence).Setup(p => p.ReadByte()).Returns(0);
  77. _channelSessionMock.InSequence(sequence)
  78. .Setup(p => p.SendData(It.Is<byte[]>(b => b.SequenceEqual(CreateData(
  79. string.Format("C0644 {0} {1}\n",
  80. _fileInfo.Length,
  81. Path.GetFileName(_fileName)
  82. )
  83. )))));
  84. for (var i = 0; i < random.Next(1, 3); i++)
  85. _pipeStreamMock.InSequence(sequence).Setup(p => p.ReadByte()).Returns(-1);
  86. _pipeStreamMock.InSequence(sequence).Setup(p => p.ReadByte()).Returns(0);
  87. _channelSessionMock.InSequence(sequence)
  88. .Setup(
  89. p => p.SendData(It.Is<byte[]>(b => b.SequenceEqual(_fileContent.Take(_bufferSize))), 0, _bufferSize));
  90. _channelSessionMock.InSequence(sequence)
  91. .Setup(
  92. p => p.SendData(It.Is<byte[]>(b => b.Take(0, _fileContent.Length - _bufferSize).SequenceEqual(_fileContent.Take(_bufferSize, _fileContent.Length - _bufferSize))), 0, _fileContent.Length - _bufferSize));
  93. _channelSessionMock.InSequence(sequence)
  94. .Setup(
  95. p => p.SendData(It.Is<byte[]>(b => b.SequenceEqual(new byte[] { 0 }))));
  96. for (var i = 0; i < random.Next(1, 3); i++)
  97. _pipeStreamMock.InSequence(sequence).Setup(p => p.ReadByte()).Returns(-1);
  98. _pipeStreamMock.InSequence(sequence).Setup(p => p.ReadByte()).Returns(0);
  99. _channelSessionMock.InSequence(sequence).Setup(p => p.Close());
  100. _channelSessionMock.InSequence(sequence).Setup(p => p.Dispose());
  101. _pipeStreamMock.As<IDisposable>().InSequence(sequence).Setup(p => p.Dispose());
  102. _scpClient = new ScpClient(_connectionInfo, false, _serviceFactoryMock.Object)
  103. {
  104. BufferSize = (uint) _bufferSize
  105. };
  106. _scpClient.Uploading += (sender, args) => _uploadingRegister.Add(args);
  107. _scpClient.Connect();
  108. }
  109. protected virtual void Act()
  110. {
  111. _scpClient.Upload(_fileInfo, _path);
  112. }
  113. [TestMethod]
  114. public void SendExecRequestOnChannelSessionShouldBeInvokedOnce()
  115. {
  116. _channelSessionMock.Verify(p => p.SendExecRequest(string.Format("scp -t \"{0}\"", _path)), Times.Once);
  117. }
  118. [TestMethod]
  119. public void CloseOnChannelShouldBeInvokedOnce()
  120. {
  121. _channelSessionMock.Verify(p => p.Close(), Times.Once);
  122. }
  123. [TestMethod]
  124. public void DisposeOnChannelShouldBeInvokedOnce()
  125. {
  126. _channelSessionMock.Verify(p => p.Dispose(), Times.Once);
  127. }
  128. [TestMethod]
  129. public void DisposeOnPipeStreamShouldBeInvokedOnce()
  130. {
  131. _pipeStreamMock.As<IDisposable>().Verify(p => p.Dispose(), Times.Once);
  132. }
  133. [TestMethod]
  134. public void UploadingShouldHaveFiredTwice()
  135. {
  136. Assert.AreEqual(2, _uploadingRegister.Count);
  137. var uploading = _uploadingRegister[0];
  138. Assert.IsNotNull(uploading);
  139. Assert.AreSame(_fileInfo.Name, uploading.Filename);
  140. Assert.AreEqual(_fileSize, uploading.Size);
  141. Assert.AreEqual(_bufferSize, uploading.Uploaded);
  142. uploading = _uploadingRegister[1];
  143. Assert.IsNotNull(uploading);
  144. Assert.AreSame(_fileInfo.Name, uploading.Filename);
  145. Assert.AreEqual(_fileSize, uploading.Size);
  146. Assert.AreEqual(_fileSize, uploading.Uploaded);
  147. }
  148. private IEnumerable<byte> CreateData(string command)
  149. {
  150. return Encoding.Default.GetBytes(command);
  151. }
  152. private byte[] CreateContent(int length)
  153. {
  154. var random = new Random();
  155. var content = new byte[length];
  156. for (var i = 0; i < length; i++)
  157. content[i] = (byte) random.Next(byte.MinValue, byte.MaxValue);
  158. return content;
  159. }
  160. private string CreateTemporaryFile(byte[] content)
  161. {
  162. var tempFile = Path.GetTempFileName();
  163. using (var fs = File.OpenWrite(tempFile))
  164. {
  165. fs.Write(content, 0, content.Length);
  166. }
  167. return tempFile;
  168. }
  169. }
  170. }