UploadDownloadFileTest.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using Microsoft.VisualStudio.TestTools.UnitTesting;
  6. using Renci.SshNet.Common;
  7. using Renci.SshNet.Tests.Properties;
  8. using System.IO;
  9. using System.Security.Cryptography;
  10. using Renci.SshNet.Sftp;
  11. using System.Threading;
  12. namespace Renci.SshNet.Tests.SftpClientTests
  13. {
  14. [TestClass]
  15. public class UploadDownloadFileTest
  16. {
  17. [TestInitialize()]
  18. public void CleanCurrentFolder()
  19. {
  20. using (var client = new SshClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD))
  21. {
  22. client.Connect();
  23. client.RunCommand("rm -rf *");
  24. client.Disconnect();
  25. }
  26. }
  27. [TestMethod]
  28. [TestCategory("Sftp")]
  29. public void Test_Sftp_Upload_And_Download_1MB_File()
  30. {
  31. using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD))
  32. {
  33. sftp.Connect();
  34. string uploadedFileName = Path.GetTempFileName();
  35. string remoteFileName = Path.GetRandomFileName();
  36. this.CreateTestFile(uploadedFileName, 1);
  37. // Calculate has value
  38. var uploadedHash = CalculateMD5(uploadedFileName);
  39. using (var file = File.OpenRead(uploadedFileName))
  40. {
  41. sftp.UploadFile(file, remoteFileName);
  42. }
  43. string downloadedFileName = Path.GetTempFileName();
  44. using (var file = File.OpenWrite(downloadedFileName))
  45. {
  46. sftp.DownloadFile(remoteFileName, file);
  47. }
  48. var downloadedHash = CalculateMD5(downloadedFileName);
  49. sftp.DeleteFile(remoteFileName);
  50. File.Delete(uploadedFileName);
  51. File.Delete(downloadedFileName);
  52. sftp.Disconnect();
  53. Assert.AreEqual(uploadedHash, downloadedHash);
  54. }
  55. }
  56. [TestMethod]
  57. [TestCategory("Sftp")]
  58. public void Test_Sftp_Upload_Forbidden()
  59. {
  60. using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD))
  61. {
  62. sftp.Connect();
  63. string uploadedFileName = Path.GetTempFileName();
  64. string remoteFileName = "/etc/audit/ddd";
  65. this.CreateTestFile(uploadedFileName, 1);
  66. var exceptionOccured = false;
  67. try
  68. {
  69. using (var file = File.OpenRead(uploadedFileName))
  70. {
  71. sftp.UploadFile(file, remoteFileName);
  72. }
  73. }
  74. catch (SshPermissionDeniedException)
  75. {
  76. exceptionOccured = true;
  77. }
  78. sftp.Disconnect();
  79. Assert.IsTrue(exceptionOccured);
  80. }
  81. }
  82. [TestMethod]
  83. [TestCategory("Sftp")]
  84. public void Test_Sftp_Download_Forbidden()
  85. {
  86. if (Resources.USERNAME == "root")
  87. Assert.Fail("Must not run this test as root!");
  88. using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD))
  89. {
  90. sftp.Connect();
  91. string remoteFileName = "/root/install.log";
  92. var exceptionOccured = false;
  93. try
  94. {
  95. using (var ms = new MemoryStream())
  96. {
  97. sftp.UploadFile(ms, remoteFileName);
  98. }
  99. }
  100. catch (SshPermissionDeniedException)
  101. {
  102. exceptionOccured = true;
  103. }
  104. sftp.Disconnect();
  105. Assert.IsTrue(exceptionOccured);
  106. }
  107. }
  108. [TestMethod]
  109. [TestCategory("Sftp")]
  110. public void Test_Sftp_Download_File_Not_Exists()
  111. {
  112. using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD))
  113. {
  114. sftp.Connect();
  115. string remoteFileName = "/xxx/eee/yyy";
  116. var exceptionOccured = false;
  117. try
  118. {
  119. using (var ms = new MemoryStream())
  120. {
  121. sftp.UploadFile(ms, remoteFileName);
  122. }
  123. }
  124. catch (SshFileNotFoundException)
  125. {
  126. exceptionOccured = true;
  127. }
  128. sftp.Disconnect();
  129. Assert.IsTrue(exceptionOccured);
  130. }
  131. }
  132. [TestMethod]
  133. [TestCategory("Sftp")]
  134. public void Test_Sftp_Multiple_Async_Upload_And_Download_10Files_5MB_Each()
  135. {
  136. var maxFiles = 10;
  137. var maxSize = 5;
  138. using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD))
  139. {
  140. sftp.Connect();
  141. var testInfoList = new Dictionary<string, TestInfo>();
  142. for (int i = 0; i < maxFiles; i++)
  143. {
  144. var testInfo = new TestInfo();
  145. testInfo.UploadedFileName = Path.GetTempFileName();
  146. testInfo.DownloadedFileName = Path.GetTempFileName();
  147. testInfo.RemoteFileName = Path.GetRandomFileName();
  148. this.CreateTestFile(testInfo.UploadedFileName, maxSize);
  149. // Calculate hash value
  150. testInfo.UploadedHash = CalculateMD5(testInfo.UploadedFileName);
  151. testInfoList.Add(testInfo.RemoteFileName, testInfo);
  152. }
  153. var uploadWaitHandles = new List<WaitHandle>();
  154. // Start file uploads
  155. foreach (var remoteFile in testInfoList.Keys)
  156. {
  157. var testInfo = testInfoList[remoteFile];
  158. testInfo.UploadedFile = File.OpenRead(testInfo.UploadedFileName);
  159. testInfo.UploadResult = sftp.BeginUploadFile(testInfo.UploadedFile, remoteFile, null, null);
  160. uploadWaitHandles.Add(testInfo.UploadResult.AsyncWaitHandle);
  161. }
  162. // Wait for upload to finish
  163. bool uploadCompleted = false;
  164. while (!uploadCompleted)
  165. {
  166. // Assume upload completed
  167. uploadCompleted = true;
  168. foreach (var testInfo in testInfoList.Values)
  169. {
  170. SftpAsyncResult sftpResult = testInfo.UploadResult as SftpAsyncResult;
  171. testInfo.UploadedBytes = sftpResult.UploadedBytes;
  172. if (!testInfo.UploadResult.IsCompleted)
  173. {
  174. uploadCompleted = false;
  175. }
  176. }
  177. Thread.Sleep(500);
  178. }
  179. // End file uploads
  180. foreach (var remoteFile in testInfoList.Keys)
  181. {
  182. var testInfo = testInfoList[remoteFile];
  183. sftp.EndUploadFile(testInfo.UploadResult);
  184. testInfo.UploadedFile.Dispose();
  185. }
  186. // Start file downloads
  187. var downloadWaitHandles = new List<WaitHandle>();
  188. foreach (var remoteFile in testInfoList.Keys)
  189. {
  190. var testInfo = testInfoList[remoteFile];
  191. testInfo.DownloadedFile = File.OpenWrite(testInfo.DownloadedFileName);
  192. testInfo.DownloadResult = sftp.BeginDownloadFile(remoteFile, testInfo.DownloadedFile, null, null);
  193. downloadWaitHandles.Add(testInfo.DownloadResult.AsyncWaitHandle);
  194. }
  195. // Wait for download to finish
  196. bool downloadCompleted = false;
  197. while (!downloadCompleted)
  198. {
  199. // Assume download completed
  200. downloadCompleted = true;
  201. foreach (var testInfo in testInfoList.Values)
  202. {
  203. SftpAsyncResult sftpResult = testInfo.DownloadResult as SftpAsyncResult;
  204. testInfo.DownloadedBytes = sftpResult.DownloadedBytes;
  205. if (!testInfo.DownloadResult.IsCompleted)
  206. {
  207. downloadCompleted = false;
  208. }
  209. }
  210. Thread.Sleep(500);
  211. }
  212. var hashMatches = true;
  213. var uploadDownloadSizeOk = true;
  214. // End file downloads
  215. foreach (var remoteFile in testInfoList.Keys)
  216. {
  217. var testInfo = testInfoList[remoteFile];
  218. sftp.EndDownloadFile(testInfo.DownloadResult);
  219. testInfo.DownloadedFile.Dispose();
  220. testInfo.DownloadedHash = CalculateMD5(testInfo.DownloadedFileName);
  221. if (!(testInfo.UploadedBytes > 0 && testInfo.DownloadedBytes > 0 && testInfo.DownloadedBytes == testInfo.UploadedBytes))
  222. {
  223. uploadDownloadSizeOk = false;
  224. }
  225. if (!testInfo.DownloadedHash.Equals(testInfo.UploadedHash))
  226. {
  227. hashMatches = false;
  228. }
  229. }
  230. // Clean up after test
  231. foreach (var remoteFile in testInfoList.Keys)
  232. {
  233. var testInfo = testInfoList[remoteFile];
  234. sftp.DeleteFile(remoteFile);
  235. File.Delete(testInfo.UploadedFileName);
  236. File.Delete(testInfo.DownloadedFileName);
  237. }
  238. sftp.Disconnect();
  239. Assert.IsTrue(hashMatches, "Hash does not match");
  240. Assert.IsTrue(uploadDownloadSizeOk, "Uploaded and downloaded bytes does not match");
  241. }
  242. }
  243. [TestMethod]
  244. [TestCategory("Sftp")]
  245. [Description("Test that delegates passed to BeginUploadFile, BeginDownloadFile and BeginListDirectory are actually called.")]
  246. public void Test_Sftp_Ensure_Async_Delegates_Called_For_BeginFileUpload_BeginFileDownload_BeginListDirectory()
  247. {
  248. using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD))
  249. {
  250. sftp.Connect();
  251. string remoteFileName = Path.GetRandomFileName();
  252. string localFileName = Path.GetRandomFileName();
  253. bool uploadDelegateCalled = false;
  254. bool downloadDelegateCalled = false;
  255. bool listDirectoryDelegateCalled = false;
  256. IAsyncResult asyncResult;
  257. // Test for BeginUploadFile.
  258. CreateTestFile(localFileName, 1);
  259. using (var fileStream = File.OpenRead(localFileName))
  260. {
  261. asyncResult = sftp.BeginUploadFile(fileStream, remoteFileName, delegate(IAsyncResult ar)
  262. {
  263. sftp.EndUploadFile(ar);
  264. uploadDelegateCalled = true;
  265. }, null);
  266. while (!asyncResult.IsCompleted)
  267. {
  268. Thread.Sleep(500);
  269. }
  270. }
  271. File.Delete(localFileName);
  272. Assert.IsTrue(uploadDelegateCalled, "BeginUploadFile");
  273. // Test for BeginDownloadFile.
  274. asyncResult = null;
  275. using (var fileStream = File.OpenWrite(localFileName))
  276. {
  277. asyncResult = sftp.BeginDownloadFile(remoteFileName, fileStream, delegate(IAsyncResult ar)
  278. {
  279. sftp.EndDownloadFile(ar);
  280. downloadDelegateCalled = true;
  281. }, null);
  282. while (!asyncResult.IsCompleted)
  283. {
  284. Thread.Sleep(500);
  285. }
  286. }
  287. File.Delete(localFileName);
  288. Assert.IsTrue(downloadDelegateCalled, "BeginDownloadFile");
  289. // Test for BeginListDirectory.
  290. asyncResult = null;
  291. asyncResult = sftp.BeginListDirectory(sftp.WorkingDirectory, delegate(IAsyncResult ar)
  292. {
  293. sftp.EndListDirectory(ar);
  294. listDirectoryDelegateCalled = true;
  295. }, null);
  296. while (!asyncResult.IsCompleted)
  297. {
  298. Thread.Sleep(500);
  299. }
  300. Assert.IsTrue(listDirectoryDelegateCalled, "BeginListDirectory");
  301. }
  302. }
  303. [TestMethod]
  304. [TestCategory("Sftp")]
  305. [Description("Test passing null to BeginUploadFile")]
  306. [ExpectedException(typeof(ArgumentNullException))]
  307. public void Test_Sftp_BeginUploadFile_StreamIsNull()
  308. {
  309. using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD))
  310. {
  311. sftp.Connect();
  312. sftp.BeginUploadFile(null, "aaaaa", null, null);
  313. sftp.Disconnect();
  314. }
  315. }
  316. [TestMethod]
  317. [TestCategory("Sftp")]
  318. [Description("Test passing null to BeginUploadFile")]
  319. [ExpectedException(typeof(ArgumentException))]
  320. public void Test_Sftp_BeginUploadFile_FileNameIsWhiteSpace()
  321. {
  322. using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD))
  323. {
  324. sftp.Connect();
  325. sftp.BeginUploadFile(new MemoryStream(), " ", null, null);
  326. sftp.Disconnect();
  327. }
  328. }
  329. [TestMethod]
  330. [TestCategory("Sftp")]
  331. [Description("Test passing null to BeginUploadFile")]
  332. [ExpectedException(typeof(ArgumentException))]
  333. public void Test_Sftp_BeginUploadFile_FileNameIsNull()
  334. {
  335. using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD))
  336. {
  337. sftp.Connect();
  338. sftp.BeginUploadFile(new MemoryStream(), null, null, null);
  339. sftp.Disconnect();
  340. }
  341. }
  342. [TestMethod]
  343. [TestCategory("Sftp")]
  344. [Description("Test passing null to BeginDownloadFile")]
  345. [ExpectedException(typeof(ArgumentNullException))]
  346. public void Test_Sftp_BeginDownloadFile_StreamIsNull()
  347. {
  348. using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD))
  349. {
  350. sftp.Connect();
  351. sftp.BeginDownloadFile("aaaa", null, null, null);
  352. sftp.Disconnect();
  353. }
  354. }
  355. [TestMethod]
  356. [TestCategory("Sftp")]
  357. [Description("Test passing null to BeginDownloadFile")]
  358. [ExpectedException(typeof(ArgumentException))]
  359. public void Test_Sftp_BeginDownloadFile_FileNameIsWhiteSpace()
  360. {
  361. using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD))
  362. {
  363. sftp.Connect();
  364. sftp.BeginDownloadFile(" ", new MemoryStream(), null, null);
  365. sftp.Disconnect();
  366. }
  367. }
  368. [TestMethod]
  369. [TestCategory("Sftp")]
  370. [Description("Test passing null to BeginDownloadFile")]
  371. [ExpectedException(typeof(ArgumentException))]
  372. public void Test_Sftp_BeginDownloadFile_FileNameIsNull()
  373. {
  374. using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD))
  375. {
  376. sftp.Connect();
  377. sftp.BeginDownloadFile(null, new MemoryStream(), null, null);
  378. sftp.Disconnect();
  379. }
  380. }
  381. /// <summary>
  382. /// Creates the test file.
  383. /// </summary>
  384. /// <param name="fileName">Name of the file.</param>
  385. /// <param name="size">Size in megabytes.</param>
  386. private void CreateTestFile(string fileName, int size)
  387. {
  388. using (var testFile = File.Create(fileName))
  389. {
  390. var random = new Random();
  391. for (int i = 0; i < 1024 * size; i++)
  392. {
  393. var buffer = new byte[1024];
  394. random.NextBytes(buffer);
  395. testFile.Write(buffer, 0, buffer.Length);
  396. }
  397. }
  398. }
  399. protected static string CalculateMD5(string fileName)
  400. {
  401. using (FileStream file = new FileStream(fileName, FileMode.Open))
  402. {
  403. MD5 md5 = new MD5CryptoServiceProvider();
  404. byte[] retVal = md5.ComputeHash(file);
  405. file.Close();
  406. StringBuilder sb = new StringBuilder();
  407. for (int i = 0; i < retVal.Length; i++)
  408. {
  409. sb.Append(retVal[i].ToString("x2"));
  410. }
  411. return sb.ToString();
  412. }
  413. }
  414. /// <summary>
  415. /// Helper class to help with upload and download testing
  416. /// </summary>
  417. private class TestInfo
  418. {
  419. public string RemoteFileName { get; set; }
  420. public string UploadedFileName { get; set; }
  421. public string DownloadedFileName { get; set; }
  422. public ulong UploadedBytes { get; set; }
  423. public ulong DownloadedBytes { get; set; }
  424. public FileStream UploadedFile { get; set; }
  425. public FileStream DownloadedFile { get; set; }
  426. public string UploadedHash { get; set; }
  427. public string DownloadedHash { get; set; }
  428. public IAsyncResult UploadResult { get; set; }
  429. public IAsyncResult DownloadResult { get; set; }
  430. }
  431. }
  432. }