using System; using System.Collections.Generic; using System.IO; using System.Threading; using Microsoft.VisualStudio.TestTools.UnitTesting; using Renci.SshNet.Common; using Renci.SshNet.Sftp; using Renci.SshNet.Tests.Properties; namespace Renci.SshNet.Tests.Classes { /// /// Implementation of the SSH File Transfer Protocol (SFTP) over SSH. /// public partial class SftpClientTest { [TestMethod] [TestCategory("Sftp")] [TestCategory("integration")] public void Test_Sftp_Upload_And_Download_1MB_File() { RemoveAllFiles(); using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD)) { sftp.Connect(); var uploadedFileName = Path.GetTempFileName(); var remoteFileName = Path.GetRandomFileName(); CreateTestFile(uploadedFileName, 1); // Calculate has value var uploadedHash = CalculateMD5(uploadedFileName); using (var file = File.OpenRead(uploadedFileName)) { sftp.UploadFile(file, remoteFileName); } var downloadedFileName = Path.GetTempFileName(); using (var file = File.OpenWrite(downloadedFileName)) { sftp.DownloadFile(remoteFileName, file); } var downloadedHash = CalculateMD5(downloadedFileName); sftp.DeleteFile(remoteFileName); File.Delete(uploadedFileName); File.Delete(downloadedFileName); sftp.Disconnect(); Assert.AreEqual(uploadedHash, downloadedHash); } } [TestMethod] [TestCategory("Sftp")] [TestCategory("integration")] [ExpectedException(typeof(SftpPermissionDeniedException))] public void Test_Sftp_Upload_Forbidden() { using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD)) { sftp.Connect(); var uploadedFileName = Path.GetTempFileName(); var remoteFileName = "/root/1"; CreateTestFile(uploadedFileName, 1); using (var file = File.OpenRead(uploadedFileName)) { sftp.UploadFile(file, remoteFileName); } sftp.Disconnect(); } } [TestMethod] [TestCategory("Sftp")] [TestCategory("integration")] public void Test_Sftp_Multiple_Async_Upload_And_Download_10Files_5MB_Each() { var maxFiles = 10; var maxSize = 5; RemoveAllFiles(); using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD)) { sftp.Connect(); var testInfoList = new Dictionary(); for (var i = 0; i < maxFiles; i++) { var testInfo = new TestInfo { UploadedFileName = Path.GetTempFileName(), DownloadedFileName = Path.GetTempFileName(), RemoteFileName = Path.GetRandomFileName() }; CreateTestFile(testInfo.UploadedFileName, maxSize); // Calculate hash value testInfo.UploadedHash = CalculateMD5(testInfo.UploadedFileName); testInfoList.Add(testInfo.RemoteFileName, testInfo); } var uploadWaitHandles = new List(); // Start file uploads foreach (var remoteFile in testInfoList.Keys) { var testInfo = testInfoList[remoteFile]; testInfo.UploadedFile = File.OpenRead(testInfo.UploadedFileName); testInfo.UploadResult = sftp.BeginUploadFile(testInfo.UploadedFile, remoteFile, null, null) as SftpUploadAsyncResult; uploadWaitHandles.Add(testInfo.UploadResult.AsyncWaitHandle); } // Wait for upload to finish var uploadCompleted = false; while (!uploadCompleted) { // Assume upload completed uploadCompleted = true; foreach (var testInfo in testInfoList.Values) { var sftpResult = testInfo.UploadResult; if (!testInfo.UploadResult.IsCompleted) { uploadCompleted = false; } } Thread.Sleep(500); } // End file uploads foreach (var remoteFile in testInfoList.Keys) { var testInfo = testInfoList[remoteFile]; sftp.EndUploadFile(testInfo.UploadResult); testInfo.UploadedFile.Dispose(); } // Start file downloads var downloadWaitHandles = new List(); foreach (var remoteFile in testInfoList.Keys) { var testInfo = testInfoList[remoteFile]; testInfo.DownloadedFile = File.OpenWrite(testInfo.DownloadedFileName); testInfo.DownloadResult = sftp.BeginDownloadFile(remoteFile, testInfo.DownloadedFile, null, null) as SftpDownloadAsyncResult; downloadWaitHandles.Add(testInfo.DownloadResult.AsyncWaitHandle); } // Wait for download to finish var downloadCompleted = false; while (!downloadCompleted) { // Assume download completed downloadCompleted = true; foreach (var testInfo in testInfoList.Values) { var sftpResult = testInfo.DownloadResult; if (!testInfo.DownloadResult.IsCompleted) { downloadCompleted = false; } } Thread.Sleep(500); } var hashMatches = true; var uploadDownloadSizeOk = true; // End file downloads foreach (var remoteFile in testInfoList.Keys) { var testInfo = testInfoList[remoteFile]; sftp.EndDownloadFile(testInfo.DownloadResult); testInfo.DownloadedFile.Dispose(); testInfo.DownloadedHash = CalculateMD5(testInfo.DownloadedFileName); if (!(testInfo.UploadResult.UploadedBytes > 0 && testInfo.DownloadResult.DownloadedBytes > 0 && testInfo.DownloadResult.DownloadedBytes == testInfo.UploadResult.UploadedBytes)) { uploadDownloadSizeOk = false; } if (!testInfo.DownloadedHash.Equals(testInfo.UploadedHash)) { hashMatches = false; } } // Clean up after test foreach (var remoteFile in testInfoList.Keys) { var testInfo = testInfoList[remoteFile]; sftp.DeleteFile(remoteFile); File.Delete(testInfo.UploadedFileName); File.Delete(testInfo.DownloadedFileName); } sftp.Disconnect(); Assert.IsTrue(hashMatches, "Hash does not match"); Assert.IsTrue(uploadDownloadSizeOk, "Uploaded and downloaded bytes does not match"); } } // TODO: Split this test into multiple tests [TestMethod] [TestCategory("Sftp")] [TestCategory("integration")] [Description("Test that delegates passed to BeginUploadFile, BeginDownloadFile and BeginListDirectory are actually called.")] public void Test_Sftp_Ensure_Async_Delegates_Called_For_BeginFileUpload_BeginFileDownload_BeginListDirectory() { RemoveAllFiles(); using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD)) { sftp.Connect(); var remoteFileName = Path.GetRandomFileName(); var localFileName = Path.GetRandomFileName(); var uploadDelegateCalled = false; var downloadDelegateCalled = false; var listDirectoryDelegateCalled = false; IAsyncResult asyncResult; // Test for BeginUploadFile. CreateTestFile(localFileName, 1); using (var fileStream = File.OpenRead(localFileName)) { asyncResult = sftp.BeginUploadFile(fileStream, remoteFileName, delegate(IAsyncResult ar) { sftp.EndUploadFile(ar); uploadDelegateCalled = true; }, null); while (!asyncResult.IsCompleted) { Thread.Sleep(500); } } File.Delete(localFileName); Assert.IsTrue(uploadDelegateCalled, "BeginUploadFile"); // Test for BeginDownloadFile. asyncResult = null; using (var fileStream = File.OpenWrite(localFileName)) { asyncResult = sftp.BeginDownloadFile(remoteFileName, fileStream, delegate(IAsyncResult ar) { sftp.EndDownloadFile(ar); downloadDelegateCalled = true; }, null); while (!asyncResult.IsCompleted) { Thread.Sleep(500); } } File.Delete(localFileName); Assert.IsTrue(downloadDelegateCalled, "BeginDownloadFile"); // Test for BeginListDirectory. asyncResult = null; asyncResult = sftp.BeginListDirectory(sftp.WorkingDirectory, delegate(IAsyncResult ar) { _ = sftp.EndListDirectory(ar); listDirectoryDelegateCalled = true; }, null); while (!asyncResult.IsCompleted) { Thread.Sleep(500); } Assert.IsTrue(listDirectoryDelegateCalled, "BeginListDirectory"); } } [TestMethod] [TestCategory("Sftp")] [TestCategory("integration")] [Description("Test passing null to BeginUploadFile")] [ExpectedException(typeof(ArgumentNullException))] public void Test_Sftp_BeginUploadFile_StreamIsNull() { using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD)) { sftp.Connect(); _ = sftp.BeginUploadFile(null, "aaaaa", null, null); sftp.Disconnect(); } } [TestMethod] [TestCategory("Sftp")] [TestCategory("integration")] [Description("Test passing null to BeginUploadFile")] [ExpectedException(typeof(ArgumentException))] public void Test_Sftp_BeginUploadFile_FileNameIsWhiteSpace() { using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD)) { sftp.Connect(); _ = sftp.BeginUploadFile(new MemoryStream(), " ", null, null); sftp.Disconnect(); } } [TestMethod] [TestCategory("Sftp")] [TestCategory("integration")] [Description("Test passing null to BeginUploadFile")] [ExpectedException(typeof(ArgumentException))] public void Test_Sftp_BeginUploadFile_FileNameIsNull() { using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD)) { sftp.Connect(); _ = sftp.BeginUploadFile(new MemoryStream(), null, null, null); sftp.Disconnect(); } } [TestMethod] [TestCategory("Sftp")] [TestCategory("integration")] [ExpectedException(typeof(ArgumentException))] public void Test_Sftp_EndUploadFile_Invalid_Async_Handle() { using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD)) { sftp.Connect(); var async1 = sftp.BeginListDirectory("/", null, null); var filename = Path.GetTempFileName(); CreateTestFile(filename, 100); var async2 = sftp.BeginUploadFile(File.OpenRead(filename), "test", null, null); sftp.EndUploadFile(async1); } } } }