using Renci.SshNet.Common;
namespace Renci.SshNet.IntegrationTests
{
    // TODO SCP: UPLOAD / DOWNLOAD ZERO LENGTH FILES
    // TODO SCP: UPLOAD / DOWNLOAD EMPTY DIRECTORY
    // TODO SCP: UPLOAD DIRECTORY THAT ALREADY EXISTS ON REMOTE HOST
    [TestClass]
    public class ScpTests : TestBase
    {
        private IConnectionInfoFactory _connectionInfoFactory;
        private IRemotePathTransformation _remotePathTransformation;
        [TestInitialize]
        public void SetUp()
        {
            _connectionInfoFactory = new LinuxVMConnectionFactory(SshServerHostName, SshServerPort);
            _remotePathTransformation = RemotePathTransformation.ShellQuote;
        }
        [TestMethod]
        [DynamicData(nameof(GetScpDownloadStreamDirectoryDoesNotExistData), DynamicDataSourceType.Method)]
        public void Scp_Download_Stream_DirectoryDoesNotExist(IRemotePathTransformation remotePathTransformation,
                                                              string remotePath,
                                                              string remoteFile)
        {
            var completeRemotePath = CombinePaths(remotePath, remoteFile);
            // remove complete directory if it's not the home directory of the user
            // or else remove the remote file
            using (var client = new SftpClient(_connectionInfoFactory.Create()))
            {
                client.Connect();
                if (client.Exists(completeRemotePath))
                {
                    client.DeleteFile(completeRemotePath);
                }
                if (remotePath.Length > 0 && remotePath != client.WorkingDirectory)
                {
                    if (client.Exists(remotePath))
                    {
                        client.DeleteDirectory(remotePath);
                    }
                }
            }
            try
            {
                using (var downloaded = new MemoryStream())
                using (var client = new ScpClient(_connectionInfoFactory.Create()))
                {
                    if (remotePathTransformation != null)
                    {
                        client.RemotePathTransformation = remotePathTransformation;
                    }
                    client.Connect();
                    try
                    {
                        client.Download(completeRemotePath, downloaded);
                        Assert.Fail();
                    }
                    catch (ScpException ex)
                    {
                        Assert.IsNull(ex.InnerException);
                        Assert.AreEqual($"scp: {completeRemotePath}: No such file or directory", ex.Message);
                    }
                }
            }
            finally
            {
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    if (client.Exists(completeRemotePath))
                    {
                        client.DeleteFile(completeRemotePath);
                    }
                    if (remotePath.Length > 0 && remotePath != client.WorkingDirectory)
                    {
                        if (client.Exists(remotePath))
                        {
                            client.DeleteDirectory(remotePath);
                        }
                    }
                }
            }
        }
        [TestMethod]
        [DynamicData(nameof(GetScpDownloadStreamFileDoesNotExistData), DynamicDataSourceType.Method)]
        public void Scp_Download_Stream_FileDoesNotExist(IRemotePathTransformation remotePathTransformation,
                                                         string remotePath,
                                                         string remoteFile)
        {
            var completeRemotePath = CombinePaths(remotePath, remoteFile);
            // remove complete directory if it's not the home directory of the user
            // or else remove the remote file
            using (var client = new SftpClient(_connectionInfoFactory.Create()))
            {
                client.Connect();
                if (client.Exists(completeRemotePath))
                {
                    client.DeleteFile(completeRemotePath);
                }
                if (remotePath.Length > 0 && remotePath != client.WorkingDirectory)
                {
                    if (client.Exists(remotePath))
                    {
                        client.DeleteDirectory(remotePath);
                    }
                    client.CreateDirectory(remotePath);
                }
            }
            try
            {
                using (var downloaded = new MemoryStream())
                using (var client = new ScpClient(_connectionInfoFactory.Create()))
                {
                    if (remotePathTransformation != null)
                    {
                        client.RemotePathTransformation = remotePathTransformation;
                    }
                    client.Connect();
                    try
                    {
                        client.Download(completeRemotePath, downloaded);
                        Assert.Fail();
                    }
                    catch (ScpException ex)
                    {
                        Assert.IsNull(ex.InnerException);
                        Assert.AreEqual($"scp: {completeRemotePath}: No such file or directory", ex.Message);
                    }
                }
            }
            finally
            {
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    if (client.Exists(completeRemotePath))
                    {
                        client.DeleteFile(completeRemotePath);
                    }
                    if (remotePath.Length > 0 && remotePath != client.WorkingDirectory)
                    {
                        if (client.Exists(remotePath))
                        {
                            client.DeleteDirectory(remotePath);
                        }
                    }
                }
            }
        }
        [TestMethod]
        [DynamicData(nameof(GetScpDownloadDirectoryInfoDirectoryDoesNotExistData), DynamicDataSourceType.Method)]
        public void Scp_Download_DirectoryInfo_DirectoryDoesNotExist(IRemotePathTransformation remotePathTransformation,
                                                                     string remotePath)
        {
            var localDirectory = Path.GetTempFileName();
            File.Delete(localDirectory);
            Directory.CreateDirectory(localDirectory);
            try
            {
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    if (client.Exists(remotePath))
                    {
                        client.DeleteDirectory(remotePath);
                    }
                }
                using (var client = new ScpClient(_connectionInfoFactory.Create()))
                {
                    if (remotePathTransformation != null)
                    {
                        client.RemotePathTransformation = remotePathTransformation;
                    }
                    client.Connect();
                    try
                    {
                        client.Download(remotePath, new DirectoryInfo(localDirectory));
                        Assert.Fail();
                    }
                    catch (ScpException ex)
                    {
                        Assert.IsNull(ex.InnerException);
                        Assert.AreEqual($"scp: {remotePath}: No such file or directory", ex.Message);
                    }
                }
            }
            finally
            {
                Directory.Delete(localDirectory, true);
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    if (client.Exists(remotePath))
                    {
                        client.DeleteDirectory(remotePath);
                    }
                }
            }
        }
        [TestMethod]
        [DynamicData(nameof(GetScpDownloadDirectoryInfoExistingFileData), DynamicDataSourceType.Method)]
        public void Scp_Download_DirectoryInfo_ExistingFile(IRemotePathTransformation remotePathTransformation,
                                                            string remotePath)
        {
            var content = CreateMemoryStream(100);
            content.Position = 0;
            var localDirectory = Path.GetTempFileName();
            File.Delete(localDirectory);
            Directory.CreateDirectory(localDirectory);
            var localFile = Path.Combine(localDirectory, PosixPath.GetFileName(remotePath));
            try
            {
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    client.UploadFile(content, remotePath);
                }
                using (var client = new ScpClient(_connectionInfoFactory.Create()))
                {
                    if (remotePathTransformation != null)
                    {
                        client.RemotePathTransformation = remotePathTransformation;
                    }
                    client.Connect();
                    client.Download(remotePath, new DirectoryInfo(localDirectory));
                }
                Assert.IsTrue(File.Exists(localFile));
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    using (var downloaded = new MemoryStream())
                    {
                        client.DownloadFile(remotePath, downloaded);
                        downloaded.Position = 0;
                        Assert.AreEqual(CreateFileHash(localFile), CreateHash(downloaded));
                    }
                }
            }
            finally
            {
                Directory.Delete(localDirectory, true);
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    if (client.Exists(remotePath))
                    {
                        client.DeleteFile(remotePath);
                    }
                }
            }
        }
        [TestMethod]
        [DynamicData(nameof(GetScpDownloadDirectoryInfoExistingDirectoryData), DynamicDataSourceType.Method)]
        public void Scp_Download_DirectoryInfo_ExistingDirectory(IRemotePathTransformation remotePathTransformation,
                                                                 string remotePath)
        {
            var localDirectory = Path.GetTempFileName();
            File.Delete(localDirectory);
            Directory.CreateDirectory(localDirectory);
            var localPathFile1 = Path.Combine(localDirectory, "file1 23");
            var remotePathFile1 = CombinePaths(remotePath, "file1 23");
            var contentFile1 = CreateMemoryStream(1024);
            contentFile1.Position = 0;
            var localPathFile2 = Path.Combine(localDirectory, "file2 #$%");
            var remotePathFile2 = CombinePaths(remotePath, "file2 #$%");
            var contentFile2 = CreateMemoryStream(2048);
            contentFile2.Position = 0;
            var localPathSubDirectory = Path.Combine(localDirectory, "subdir $1%#");
            var remotePathSubDirectory = CombinePaths(remotePath, "subdir $1%#");
            var localPathFile3 = Path.Combine(localPathSubDirectory, "file3 %$#");
            var remotePathFile3 = CombinePaths(remotePathSubDirectory, "file3 %$#");
            var contentFile3 = CreateMemoryStream(256);
            contentFile3.Position = 0;
            using (var client = new SftpClient(_connectionInfoFactory.Create()))
            {
                client.Connect();
                if (client.Exists(remotePathFile1))
                {
                    client.DeleteFile(remotePathFile1);
                }
                if (client.Exists(remotePathFile2))
                {
                    client.DeleteFile(remotePathFile2);
                }
                if (client.Exists(remotePathFile3))
                {
                    client.DeleteFile(remotePathFile3);
                }
                if (client.Exists(remotePathSubDirectory))
                {
                    client.DeleteDirectory(remotePathSubDirectory);
                }
                if (remotePath.Length > 0 && remotePath != client.WorkingDirectory)
                {
                    if (client.Exists(remotePath))
                    {
                        client.DeleteDirectory(remotePath);
                    }
                }
            }
            try
            {
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    if (!client.Exists(remotePath))
                    {
                        client.CreateDirectory(remotePath);
                    }
                    client.UploadFile(contentFile1, remotePathFile1);
                    client.UploadFile(contentFile1, remotePathFile2);
                    client.CreateDirectory(remotePathSubDirectory);
                    client.UploadFile(contentFile3, remotePathFile3);
                }
                using (var client = new ScpClient(_connectionInfoFactory.Create()))
                {
                    if (remotePathTransformation != null)
                    {
                        client.RemotePathTransformation = remotePathTransformation;
                    }
                    client.Connect();
                    client.Download(remotePath, new DirectoryInfo(localDirectory));
                }
                var localFiles = Directory.GetFiles(localDirectory);
                Assert.AreEqual(2, localFiles.Length);
                Assert.IsTrue(localFiles.Contains(localPathFile1));
                Assert.IsTrue(localFiles.Contains(localPathFile2));
                var localSubDirecties = Directory.GetDirectories(localDirectory);
                Assert.AreEqual(1, localSubDirecties.Length);
                Assert.AreEqual(localPathSubDirectory, localSubDirecties[0]);
                var localFilesSubDirectory = Directory.GetFiles(localPathSubDirectory);
                Assert.AreEqual(1, localFilesSubDirectory.Length);
                Assert.AreEqual(localPathFile3, localFilesSubDirectory[0]);
                Assert.AreEqual(0, Directory.GetDirectories(localPathSubDirectory).Length);
            }
            finally
            {
                Directory.Delete(localDirectory, true);
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    if (client.Exists(remotePathFile1))
                    {
                        client.DeleteFile(remotePathFile1);
                    }
                    if (client.Exists(remotePathFile2))
                    {
                        client.DeleteFile(remotePathFile2);
                    }
                    if (client.Exists(remotePathFile3))
                    {
                        client.DeleteFile(remotePathFile3);
                    }
                    if (client.Exists(remotePathSubDirectory))
                    {
                        client.DeleteDirectory(remotePathSubDirectory);
                    }
                    if (remotePath.Length > 0 && remotePath != client.WorkingDirectory)
                    {
                        if (client.Exists(remotePath))
                        {
                            client.DeleteDirectory(remotePath);
                        }
                    }
                }
            }
        }
        [TestMethod]
        [DynamicData(nameof(GetScpDownloadFileInfoDirectoryDoesNotExistData), DynamicDataSourceType.Method)]
        public void Scp_Download_FileInfo_DirectoryDoesNotExist(IRemotePathTransformation remotePathTransformation,
                                                                string remotePath,
                                                                string remoteFile)
        {
            var completeRemotePath = CombinePaths(remotePath, remoteFile);
            // remove complete directory if it's not the home directory of the user
            // or else remove the remote file
            using (var client = new SftpClient(_connectionInfoFactory.Create()))
            {
                client.Connect();
                if (remotePath.Length > 0 && remotePath != client.WorkingDirectory)
                {
                    if (client.Exists(remotePath))
                    {
                        client.DeleteDirectory(remotePath);
                    }
                }
            }
            var fileInfo = new FileInfo(Path.GetTempFileName());
            try
            {
                using (var client = new ScpClient(_connectionInfoFactory.Create()))
                {
                    if (remotePathTransformation != null)
                    {
                        client.RemotePathTransformation = remotePathTransformation;
                    }
                    client.Connect();
                    try
                    {
                        client.Download(completeRemotePath, fileInfo);
                        Assert.Fail();
                    }
                    catch (ScpException ex)
                    {
                        Assert.IsNull(ex.InnerException);
                        Assert.AreEqual($"scp: {completeRemotePath}: No such file or directory", ex.Message);
                    }
                }
            }
            finally
            {
                fileInfo.Delete();
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    if (client.Exists(completeRemotePath))
                    {
                        client.DeleteFile(completeRemotePath);
                    }
                    if (remotePath.Length > 0 && remotePath != client.WorkingDirectory)
                    {
                        if (client.Exists(remotePath))
                        {
                            client.DeleteDirectory(remotePath);
                        }
                    }
                }
            }
        }
        [TestMethod]
        [DynamicData(nameof(GetScpDownloadFileInfoFileDoesNotExistData), DynamicDataSourceType.Method)]
        public void Scp_Download_FileInfo_FileDoesNotExist(IRemotePathTransformation remotePathTransformation,
                                                           string remotePath,
                                                           string remoteFile)
        {
            var completeRemotePath = CombinePaths(remotePath, remoteFile);
            // remove complete directory if it's not the home directory of the user
            // or else remove the remote file
            using (var client = new SftpClient(_connectionInfoFactory.Create()))
            {
                client.Connect();
                if (remotePath.Length > 0 && remotePath != client.WorkingDirectory)
                {
                    if (client.Exists(remotePath))
                    {
                        client.DeleteDirectory(remotePath);
                    }
                    client.CreateDirectory(remotePath);
                }
            }
            var fileInfo = new FileInfo(Path.GetTempFileName());
            try
            {
                using (var client = new ScpClient(_connectionInfoFactory.Create()))
                {
                    if (remotePathTransformation != null)
                    {
                        client.RemotePathTransformation = remotePathTransformation;
                    }
                    client.Connect();
                    try
                    {
                        client.Download(completeRemotePath, fileInfo);
                        Assert.Fail();
                    }
                    catch (ScpException ex)
                    {
                        Assert.IsNull(ex.InnerException);
                        Assert.AreEqual($"scp: {completeRemotePath}: No such file or directory", ex.Message);
                    }
                }
            }
            finally
            {
                fileInfo.Delete();
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    if (client.Exists(completeRemotePath))
                    {
                        client.DeleteFile(completeRemotePath);
                    }
                    if (remotePath.Length > 0 && remotePath != client.WorkingDirectory)
                    {
                        if (client.Exists(remotePath))
                        {
                            client.DeleteDirectory(remotePath);
                        }
                    }
                }
            }
        }
        [TestMethod]
        [DynamicData(nameof(GetScpDownloadFileInfoExistingDirectoryData), DynamicDataSourceType.Method)]
        public void Scp_Download_FileInfo_ExistingDirectory(IRemotePathTransformation remotePathTransformation,
                                                            string remotePath)
        {
            // remove complete directory if it's not the home directory of the user
            // or else remove the remote file
            using (var client = new SftpClient(_connectionInfoFactory.Create()))
            {
                client.Connect();
                if (remotePath.Length > 0 && remotePath != client.WorkingDirectory)
                {
                    if (client.Exists(remotePath))
                    {
                        client.DeleteDirectory(remotePath);
                    }
                    client.CreateDirectory(remotePath);
                }
            }
            var fileInfo = new FileInfo(Path.GetTempFileName());
            fileInfo.Delete();
            try
            {
                using (var client = new ScpClient(_connectionInfoFactory.Create()))
                {
                    if (remotePathTransformation != null)
                    {
                        client.RemotePathTransformation = remotePathTransformation;
                    }
                    client.Connect();
                    try
                    {
                        client.Download(remotePath, fileInfo);
                        Assert.Fail();
                    }
                    catch (ScpException ex)
                    {
                        Assert.IsNull(ex.InnerException);
                        Assert.AreEqual($"scp: {remotePath}: not a regular file", ex.Message);
                    }
                    Assert.IsFalse(fileInfo.Exists);
                }
            }
            finally
            {
                fileInfo.Delete();
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    if (remotePath.Length > 0 && remotePath != client.WorkingDirectory)
                    {
                        if (client.Exists(remotePath))
                        {
                            client.DeleteDirectory(remotePath);
                        }
                    }
                }
            }
        }
        [TestMethod]
        [DynamicData(nameof(GetScpDownloadFileInfoExistingFileData), DynamicDataSourceType.Method)]
        public void Scp_Download_FileInfo_ExistingFile(IRemotePathTransformation remotePathTransformation,
                                                       string remotePath,
                                                       string remoteFile,
                                                       int size)
        {
            var completeRemotePath = CombinePaths(remotePath, remoteFile);
            // remove complete directory if it's not the home directory of the user
            // or else remove the remote file
            using (var client = new SftpClient(_connectionInfoFactory.Create()))
            {
                client.Connect();
                if (client.Exists(completeRemotePath))
                {
                    client.DeleteFile(completeRemotePath);
                }
                if (remotePath.Length > 0 && remotePath != client.WorkingDirectory)
                {
                    if (client.Exists(remotePath))
                    {
                        client.DeleteDirectory(remotePath);
                    }
                    client.CreateDirectory(remotePath);
                }
            }
            var fileInfo = new FileInfo(Path.GetTempFileName());
            try
            {
                var content = CreateMemoryStream(size);
                content.Position = 0;
                using (var client = new ScpClient(_connectionInfoFactory.Create()))
                {
                    if (remotePathTransformation != null)
                    {
                        client.RemotePathTransformation = remotePathTransformation;
                    }
                    client.Connect();
                    client.Upload(content, completeRemotePath);
                }
                using (var client = new ScpClient(_connectionInfoFactory.Create()))
                {
                    if (remotePathTransformation != null)
                    {
                        client.RemotePathTransformation = remotePathTransformation;
                    }
                    client.Connect();
                    client.Download(completeRemotePath, fileInfo);
                }
                using (var fs = fileInfo.OpenRead())
                {
                    var downloadedBytes = new byte[fs.Length];
                    Assert.AreEqual(downloadedBytes.Length, fs.Read(downloadedBytes, 0, downloadedBytes.Length));
                    content.Position = 0;
                    Assert.AreEqual(CreateHash(content), CreateHash(downloadedBytes));
                }
            }
            finally
            {
                fileInfo.Delete();
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    if (client.Exists(completeRemotePath))
                    {
                        client.DeleteFile(completeRemotePath);
                    }
                    if (remotePath.Length > 0 && remotePath != client.WorkingDirectory)
                    {
                        if (client.Exists(remotePath))
                        {
                            client.DeleteDirectory(remotePath);
                        }
                    }
                }
            }
        }
        [TestMethod]
        [DynamicData(nameof(GetScpDownloadStreamExistingDirectoryData), DynamicDataSourceType.Method)]
        public void Scp_Download_Stream_ExistingDirectory(IRemotePathTransformation remotePathTransformation,
                                                          string remotePath)
        {
            using (var client = new SftpClient(_connectionInfoFactory.Create()))
            {
                client.Connect();
                if (remotePath.Length > 0 && remotePath != client.WorkingDirectory)
                {
                    if (client.Exists(remotePath))
                    {
                        client.DeleteDirectory(remotePath);
                    }
                    client.CreateDirectory(remotePath);
                }
            }
            var file = Path.GetTempFileName();
            File.Delete(file);
            try
            {
                using (var fs = File.OpenWrite(file))
                using (var client = new ScpClient(_connectionInfoFactory.Create()))
                {
                    if (remotePathTransformation != null)
                    {
                        client.RemotePathTransformation = remotePathTransformation;
                    }
                    client.Connect();
                    try
                    {
                        client.Download(remotePath, fs);
                        Assert.Fail();
                    }
                    catch (ScpException ex)
                    {
                        Assert.IsNull(ex.InnerException);
                        Assert.AreEqual($"scp: {remotePath}: not a regular file", ex.Message);
                    }
                    Assert.AreEqual(0, fs.Length);
                }
            }
            finally
            {
                File.Delete(file);
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    if (remotePath.Length > 0 && remotePath != client.WorkingDirectory)
                    {
                        if (client.Exists(remotePath))
                        {
                            client.DeleteDirectory(remotePath);
                        }
                    }
                }
            }
        }
        [TestMethod]
        [DynamicData(nameof(GetScpDownloadStreamExistingFileData), DynamicDataSourceType.Method)]
        public void Scp_Download_Stream_ExistingFile(IRemotePathTransformation remotePathTransformation,
                                                     string remotePath,
                                                     string remoteFile,
                                                     int size)
        {
            var completeRemotePath = CombinePaths(remotePath, remoteFile);
            // remove complete directory if it's not the home directory of the user
            // or else remove the remote file
            using (var client = new SftpClient(_connectionInfoFactory.Create()))
            {
                client.Connect();
                if (client.Exists(completeRemotePath))
                {
                    client.DeleteFile(completeRemotePath);
                }
                if (remotePath.Length > 0 && remotePath != client.WorkingDirectory)
                {
                    if (client.Exists(remotePath))
                    {
                        client.DeleteDirectory(remotePath);
                    }
                    client.CreateDirectory(remotePath);
                }
            }
            var file = CreateTempFile(size);
            try
            {
                using (var fs = File.OpenRead(file))
                using (var client = new ScpClient(_connectionInfoFactory.Create()))
                {
                    if (remotePathTransformation != null)
                    {
                        client.RemotePathTransformation = remotePathTransformation;
                    }
                    client.Connect();
                    client.Upload(fs, completeRemotePath);
                }
                using (var fs = File.OpenRead(file))
                using (var downloaded = new MemoryStream(size))
                using (var client = new ScpClient(_connectionInfoFactory.Create()))
                {
                    if (remotePathTransformation != null)
                    {
                        client.RemotePathTransformation = remotePathTransformation;
                    }
                    client.Connect();
                    client.Download(completeRemotePath, downloaded);
                    downloaded.Position = 0;
                    Assert.AreEqual(CreateHash(fs), CreateHash(downloaded));
                }
            }
            finally
            {
                File.Delete(file);
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    if (client.Exists(completeRemotePath))
                    {
                        client.DeleteFile(completeRemotePath);
                    }
                    if (remotePath.Length > 0 && remotePath != client.WorkingDirectory)
                    {
                        if (client.Exists(remotePath))
                        {
                            client.DeleteDirectory(remotePath);
                        }
                    }
                }
            }
        }
        [TestMethod]
        [DynamicData(nameof(GetScpUploadFileStreamDirectoryDoesNotExistData), DynamicDataSourceType.Method)]
        public void Scp_Upload_FileStream_DirectoryDoesNotExist(IRemotePathTransformation remotePathTransformation,
                                                                string remotePath,
                                                                string remoteFile)
        {
            var completeRemotePath = CombinePaths(remotePath, remoteFile);
            using (var client = new SftpClient(_connectionInfoFactory.Create()))
            {
                client.Connect();
                if (client.Exists(completeRemotePath))
                {
                    client.DeleteFile(completeRemotePath);
                }
                if (client.Exists(remotePath))
                {
                    client.DeleteDirectory(remotePath);
                }
            }
            var file = CreateTempFile(1000);
            try
            {
                using (var fs = File.OpenRead(file))
                using (var client = new ScpClient(_connectionInfoFactory.Create()))
                {
                    if (remotePathTransformation != null)
                    {
                        client.RemotePathTransformation = remotePathTransformation;
                    }
                    client.Connect();
                    try
                    {
                        client.Upload(fs, completeRemotePath);
                        Assert.Fail();
                    }
                    catch (ScpException ex)
                    {
                        Assert.IsNull(ex.InnerException);
                        Assert.AreEqual($"scp: {remotePath}: No such file or directory", ex.Message);
                    }
                }
            }
            finally
            {
                File.Delete(file);
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    if (client.Exists(completeRemotePath))
                    {
                        client.DeleteFile(completeRemotePath);
                    }
                    if (client.Exists(remotePath))
                    {
                        client.DeleteDirectory(remotePath);
                    }
                }
            }
        }
        [TestMethod]
        [DynamicData(nameof(GetScpUploadFileStreamExistingDirectoryData), DynamicDataSourceType.Method)]
        public void Scp_Upload_FileStream_ExistingDirectory(IRemotePathTransformation remotePathTransformation,
                                                            string remoteFile)
        {
            using (var client = new SshClient(_connectionInfoFactory.Create()))
            {
                client.Connect();
                using (var command = client.CreateCommand("rm -Rf " + _remotePathTransformation.Transform(remoteFile)))
                {
                    command.Execute();
                }
            }
            var file = CreateTempFile(1000);
            try
            {
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    client.CreateDirectory(remoteFile);
                }
                using (var fs = File.OpenRead(file))
                using (var client = new ScpClient(_connectionInfoFactory.Create()))
                {
                    if (remotePathTransformation != null)
                    {
                        client.RemotePathTransformation = remotePathTransformation;
                    }
                    client.Connect();
                    try
                    {
                        client.Upload(fs, remoteFile);
                        Assert.Fail();
                    }
                    catch (ScpException ex)
                    {
                        Assert.IsNull(ex.InnerException);
                        Assert.AreEqual($"scp: {remoteFile}: Is a directory", ex.Message);
                    }
                }
            }
            finally
            {
                File.Delete(file);
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    if (client.Exists(remoteFile))
                    {
                        client.DeleteDirectory(remoteFile);
                    }
                }
            }
        }
        [TestMethod]
        [DynamicData(nameof(ScpUploadFileStreamExistingFileData), DynamicDataSourceType.Method)]
        public void Scp_Upload_FileStream_ExistingFile(IRemotePathTransformation remotePathTransformation,
                                                       string remoteFile)
        {
            using (var client = new SftpClient(_connectionInfoFactory.Create()))
            {
                client.Connect();
                if (client.Exists(remoteFile))
                {
                    client.DeleteFile(remoteFile);
                }
            }
            // original content is bigger than new content to ensure file is fully overwritten
            var originalContent = CreateMemoryStream(2000);
            var file = CreateTempFile(1000);
            try
            {
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    originalContent.Position = 0;
                    client.UploadFile(originalContent, remoteFile);
                }
                using (var fs = File.OpenRead(file))
                using (var client = new ScpClient(_connectionInfoFactory.Create()))
                {
                    if (remotePathTransformation != null)
                    {
                        client.RemotePathTransformation = remotePathTransformation;
                    }
                    client.Connect();
                    client.Upload(fs, remoteFile);
                }
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    using (var downloaded = new MemoryStream(1000))
                    {
                        client.DownloadFile(remoteFile, downloaded);
                        downloaded.Position = 0;
                        Assert.AreEqual(CreateFileHash(file), CreateHash(downloaded));
                    }
                }
            }
            finally
            {
                File.Delete(file);
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    if (client.Exists(remoteFile))
                    {
                        client.DeleteFile(remoteFile);
                    }
                }
            }
        }
        [TestMethod]
        [DynamicData(nameof(GetScpUploadFileStreamFileDoesNotExistData), DynamicDataSourceType.Method)]
        public void Scp_Upload_FileStream_FileDoesNotExist(IRemotePathTransformation remotePathTransformation,
                                                           string remotePath,
                                                           string remoteFile,
                                                           int size)
        {
            var completeRemotePath = CombinePaths(remotePath, remoteFile);
            using (var client = new SftpClient(_connectionInfoFactory.Create()))
            {
                client.Connect();
                if (client.Exists(completeRemotePath))
                {
                    client.DeleteFile(completeRemotePath);
                }
                // remove complete directory if it's not the home directory of the user
                if (remotePath.Length > 0 && remotePath != client.WorkingDirectory)
                {
                    if (client.Exists(remotePath))
                    {
                        client.DeleteDirectory(remotePath);
                    }
                }
            }
            var file = CreateTempFile(size);
            try
            {
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    // create directory if it's not the home directory of the user
                    if (remotePath.Length > 0 && remotePath != client.WorkingDirectory)
                    {
                        if (!client.Exists((remotePath)))
                        {
                            client.CreateDirectory(remotePath);
                        }
                    }
                }
                using (var fs = File.OpenRead(file))
                using (var client = new ScpClient(_connectionInfoFactory.Create()))
                {
                    if (remotePathTransformation != null)
                    {
                        client.RemotePathTransformation = remotePathTransformation;
                    }
                    client.Connect();
                    client.Upload(fs, completeRemotePath);
                }
                using (var fs = File.OpenRead(file))
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    var sftpFile = client.Get(completeRemotePath);
                    Assert.AreEqual(GetAbsoluteRemotePath(client, remotePath, remoteFile), sftpFile.FullName);
                    Assert.AreEqual(size, sftpFile.Length);
                    var downloaded = client.ReadAllBytes(completeRemotePath);
                    Assert.AreEqual(CreateHash(fs), CreateHash(downloaded));
                }
            }
            finally
            {
                File.Delete(file);
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    if (client.Exists(completeRemotePath))
                    {
                        client.DeleteFile(completeRemotePath);
                    }
                    // remove complete directory if it's not the home directory of the user
                    if (remotePath.Length > 0 && remotePath != client.WorkingDirectory)
                    {
                        if (client.Exists(remotePath))
                        {
                            client.DeleteDirectory(remotePath);
                        }
                    }
                }
            }
        }
        /// 
        /// https://github.com/sshnet/SSH.NET/issues/289
        /// 
        [TestMethod]
        [DynamicData(nameof(GetScpUploadFileInfoDirectoryDoesNotExistData), DynamicDataSourceType.Method)]
        public void Scp_Upload_FileInfo_DirectoryDoesNotExist(IRemotePathTransformation remotePathTransformation,
                                                              string remotePath,
                                                              string remoteFile)
        {
            var completeRemotePath = CombinePaths(remotePath, remoteFile);
            using (var client = new SftpClient(_connectionInfoFactory.Create()))
            {
                client.Connect();
                if (client.Exists(completeRemotePath))
                {
                    client.DeleteFile(completeRemotePath);
                }
                if (client.Exists(remotePath))
                {
                    client.DeleteDirectory(remotePath);
                }
            }
            var file = CreateTempFile(1000);
            try
            {
                using (var client = new ScpClient(_connectionInfoFactory.Create()))
                {
                    if (remotePathTransformation != null)
                    {
                        client.RemotePathTransformation = remotePathTransformation;
                    }
                    client.Connect();
                    try
                    {
                        client.Upload(new FileInfo(file), completeRemotePath);
                        Assert.Fail();
                    }
                    catch (ScpException ex)
                    {
                        Assert.IsNull(ex.InnerException);
                        Assert.AreEqual($"scp: {remotePath}: No such file or directory", ex.Message);
                    }
                }
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    Assert.IsFalse(client.Exists(completeRemotePath));
                    Assert.IsFalse(client.Exists(remotePath));
                }
            }
            finally
            {
                File.Delete(file);
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    if (client.Exists(completeRemotePath))
                    {
                        client.DeleteFile(completeRemotePath);
                    }
                    if (client.Exists(remotePath))
                    {
                        client.DeleteDirectory(remotePath);
                    }
                }
            }
        }
        /// 
        /// https://github.com/sshnet/SSH.NET/issues/286
        /// 
        [TestMethod]
        [DynamicData(nameof(GetScpUploadFileInfoExistingDirectoryData), DynamicDataSourceType.Method)]
        public void Scp_Upload_FileInfo_ExistingDirectory(IRemotePathTransformation remotePathTransformation,
                                                          string remoteFile)
        {
            using (var client = new SshClient(_connectionInfoFactory.Create()))
            {
                client.Connect();
                using (var command = client.CreateCommand("rm -Rf " + _remotePathTransformation.Transform(remoteFile)))
                {
                    command.Execute();
                }
            }
            var file = CreateTempFile(1000);
            try
            {
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    client.CreateDirectory(remoteFile);
                }
                using (var client = new ScpClient(_connectionInfoFactory.Create()))
                {
                    if (remotePathTransformation != null)
                    {
                        client.RemotePathTransformation = remotePathTransformation;
                    }
                    client.Connect();
                    try
                    {
                        client.Upload(new FileInfo(file), remoteFile);
                        Assert.Fail();
                    }
                    catch (ScpException ex)
                    {
                        Assert.IsNull(ex.InnerException);
                        Assert.AreEqual($"scp: {remoteFile}: Is a directory", ex.Message);
                    }
                }
            }
            finally
            {
                File.Delete(file);
                using (var client = new SshClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    using (var command = client.CreateCommand("rm -Rf " + _remotePathTransformation.Transform(remoteFile)))
                    {
                        command.Execute();
                    }
                }
            }
        }
        [TestMethod]
        [DynamicData(nameof(GetScpUploadFileInfoExistingFileData), DynamicDataSourceType.Method)]
        public void Scp_Upload_FileInfo_ExistingFile(IRemotePathTransformation remotePathTransformation,
                                                     string remoteFile)
        {
            using (var client = new SftpClient(_connectionInfoFactory.Create()))
            {
                client.Connect();
                if (client.Exists(remoteFile))
                {
                    client.DeleteFile(remoteFile);
                }
            }
            // original content is bigger than new content to ensure file is fully overwritten
            var originalContent = CreateMemoryStream(2000);
            var file = CreateTempFile(1000);
            try
            {
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    originalContent.Position = 0;
                    client.UploadFile(originalContent, remoteFile);
                }
                var fileInfo = new FileInfo(file)
                {
                    LastAccessTimeUtc = new DateTime(1973, 8, 13, 20, 15, 33, DateTimeKind.Utc),
                    LastWriteTimeUtc = new DateTime(1974, 1, 24, 3, 55, 12, DateTimeKind.Utc)
                };
                using (var client = new ScpClient(_connectionInfoFactory.Create()))
                {
                    if (remotePathTransformation != null)
                    {
                        client.RemotePathTransformation = remotePathTransformation;
                    }
                    client.Connect();
                    client.Upload(fileInfo, remoteFile);
                }
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    var uploadedFile = client.Get(remoteFile);
                    Assert.AreEqual(fileInfo.LastAccessTimeUtc, uploadedFile.LastAccessTimeUtc);
                    Assert.AreEqual(fileInfo.LastWriteTimeUtc, uploadedFile.LastWriteTimeUtc);
                    using (var downloaded = new MemoryStream(1000))
                    {
                        client.DownloadFile(remoteFile, downloaded);
                        downloaded.Position = 0;
                        Assert.AreEqual(CreateFileHash(file), CreateHash(downloaded));
                    }
                }
            }
            finally
            {
                File.Delete(file);
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    if (client.Exists(remoteFile))
                    {
                        client.DeleteFile(remoteFile);
                    }
                }
            }
        }
        [TestMethod]
        [DynamicData(nameof(GetScpUploadFileInfoFileDoesNotExistData), DynamicDataSourceType.Method)]
        public void Scp_Upload_FileInfo_FileDoesNotExist(IRemotePathTransformation remotePathTransformation,
                                                         string remotePath,
                                                         string remoteFile,
                                                         int size)
        {
            var completeRemotePath = CombinePaths(remotePath, remoteFile);
            using (var client = new SftpClient(_connectionInfoFactory.Create()))
            {
                client.Connect();
                if (client.Exists(completeRemotePath))
                {
                    client.DeleteFile(completeRemotePath);
                }
                // remove complete directory if it's not the home directory of the user
                if (remotePath.Length > 0 && remotePath != client.WorkingDirectory)
                {
                    if (client.Exists(remotePath))
                    {
                        client.DeleteDirectory(remotePath);
                    }
                }
            }
            var file = CreateTempFile(size);
            try
            {
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    // create directory if it's not the home directory of the user
                    if (remotePath.Length > 0 && remotePath != client.WorkingDirectory)
                    {
                        if (!client.Exists(remotePath))
                        {
                            client.CreateDirectory(remotePath);
                        }
                    }
                }
                var fileInfo = new FileInfo(file)
                {
                    LastAccessTimeUtc = new DateTime(1973, 8, 13, 20, 15, 33, DateTimeKind.Utc),
                    LastWriteTimeUtc = new DateTime(1974, 1, 24, 3, 55, 12, DateTimeKind.Utc)
                };
                using (var client = new ScpClient(_connectionInfoFactory.Create()))
                {
                    if (remotePathTransformation != null)
                    {
                        client.RemotePathTransformation = remotePathTransformation;
                    }
                    client.Connect();
                    client.Upload(fileInfo, completeRemotePath);
                }
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    var uploadedFile = client.Get(completeRemotePath);
                    Assert.AreEqual(fileInfo.LastAccessTimeUtc, uploadedFile.LastAccessTimeUtc);
                    Assert.AreEqual(fileInfo.LastWriteTimeUtc, uploadedFile.LastWriteTimeUtc);
                    Assert.AreEqual(size, uploadedFile.Length);
                    using (var downloaded = new MemoryStream(size))
                    {
                        client.DownloadFile(completeRemotePath, downloaded);
                        downloaded.Position = 0;
                        Assert.AreEqual(CreateFileHash(file), CreateHash(downloaded));
                    }
                }
            }
            finally
            {
                File.Delete(file);
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    if (client.Exists(completeRemotePath))
                    {
                        client.Delete(completeRemotePath);
                    }
                    // remove complete directory if it's not the home directory of the user
                    if (remotePath.Length > 0 && remotePath != client.WorkingDirectory)
                    {
                        if (client.Exists(remotePath))
                        {
                            client.DeleteDirectory(remotePath);
                        }
                    }
                }
            }
        }
        [TestMethod]
        [DynamicData(nameof(GetScpUploadDirectoryInfoDirectoryDoesNotExistData), DynamicDataSourceType.Method)]
        public void Scp_Upload_DirectoryInfo_DirectoryDoesNotExist(IRemotePathTransformation remotePathTransformation,
                                                                   string remoteDirectory)
        {
            using (var client = new SftpClient(_connectionInfoFactory.Create()))
            {
                client.Connect();
                if (client.Exists((remoteDirectory)))
                {
                    client.DeleteDirectory(remoteDirectory);
                }
            }
            var localDirectory = Path.GetTempFileName();
            File.Delete(localDirectory);
            Directory.CreateDirectory(localDirectory);
            try
            {
                using (var client = new ScpClient(_connectionInfoFactory.Create()))
                {
                    if (remotePathTransformation != null)
                    {
                        client.RemotePathTransformation = remotePathTransformation;
                    }
                    client.Connect();
                    try
                    {
                        client.Upload(new DirectoryInfo(localDirectory), remoteDirectory);
                        Assert.Fail();
                    }
                    catch (ScpException ex)
                    {
                        Assert.IsNull(ex.InnerException);
                        Assert.AreEqual($"scp: {remoteDirectory}: No such file or directory", ex.Message);
                    }
                }
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    Assert.IsFalse(client.Exists(remoteDirectory));
                }
            }
            finally
            {
                Directory.Delete(localDirectory, true);
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    if (client.Exists((remoteDirectory)))
                    {
                        client.DeleteDirectory(remoteDirectory);
                    }
                }
            }
        }
        [TestMethod]
        [DynamicData(nameof(GetScpUploadDirectoryInfoExistingDirectoryData), DynamicDataSourceType.Method)]
        public void Scp_Upload_DirectoryInfo_ExistingDirectory(IRemotePathTransformation remotePathTransformation,
                                                               string remoteDirectory)
        {
            string absoluteRemoteDirectory = GetAbsoluteRemotePath(_connectionInfoFactory, remoteDirectory);
            var remotePathFile1 = CombinePaths(remoteDirectory, "file1");
            var remotePathFile2 = CombinePaths(remoteDirectory, "file2");
            var absoluteRemoteSubDirectory1 = CombinePaths(absoluteRemoteDirectory, "sub1");
            var remoteSubDirectory1 = CombinePaths(remoteDirectory, "sub1");
            var remotePathSubFile1 = CombinePaths(remoteSubDirectory1, "file1");
            var remotePathSubFile2 = CombinePaths(remoteSubDirectory1, "file2");
            var absoluteRemoteSubDirectory2 = CombinePaths(absoluteRemoteDirectory, "sub2");
            var remoteSubDirectory2 = CombinePaths(remoteDirectory, "sub2");
            using (var client = new SftpClient(_connectionInfoFactory.Create()))
            {
                client.Connect();
                if (client.Exists(remotePathSubFile1))
                {
                    client.DeleteFile(remotePathSubFile1);
                }
                if (client.Exists(remotePathSubFile2))
                {
                    client.DeleteFile(remotePathSubFile2);
                }
                if (client.Exists(remoteSubDirectory1))
                {
                    client.DeleteDirectory(remoteSubDirectory1);
                }
                if (client.Exists(remoteSubDirectory2))
                {
                    client.DeleteDirectory(remoteSubDirectory2);
                }
                if (client.Exists(remotePathFile1))
                {
                    client.DeleteFile(remotePathFile1);
                }
                if (client.Exists(remotePathFile2))
                {
                    client.DeleteFile(remotePathFile2);
                }
                if (remoteDirectory.Length > 0 && remoteDirectory != "." && remoteDirectory != client.WorkingDirectory)
                {
                    if (client.Exists(remoteDirectory))
                    {
                        client.DeleteDirectory(remoteDirectory);
                    }
                    client.CreateDirectory(remoteDirectory);
                }
            }
            var localDirectory = Path.GetTempFileName();
            File.Delete(localDirectory);
            Directory.CreateDirectory(localDirectory);
            var localPathFile1 = Path.Combine(localDirectory, "file1");
            var localPathFile2 = Path.Combine(localDirectory, "file2");
            var localSubDirectory1 = Path.Combine(localDirectory, "sub1");
            var localPathSubFile1 = Path.Combine(localSubDirectory1, "file1");
            var localPathSubFile2 = Path.Combine(localSubDirectory1, "file2");
            var localSubDirectory2 = Path.Combine(localDirectory, "sub2");
            try
            {
                CreateFile(localPathFile1, 2000);
                File.SetLastWriteTimeUtc(localPathFile1, new DateTime(2015, 8, 24, 5, 32, 16, DateTimeKind.Utc));
                CreateFile(localPathFile2, 1000);
                File.SetLastWriteTimeUtc(localPathFile2, new DateTime(2012, 3, 27, 23, 2, 54, DateTimeKind.Utc));
                // create subdirectory with two files
                Directory.CreateDirectory(localSubDirectory1);
                CreateFile(localPathSubFile1, 1000);
                File.SetLastWriteTimeUtc(localPathSubFile1, new DateTime(2013, 4, 12, 16, 54, 22, DateTimeKind.Utc));
                CreateFile(localPathSubFile2, 2000);
                File.SetLastWriteTimeUtc(localPathSubFile2, new DateTime(2015, 8, 4, 12, 43, 12, DateTimeKind.Utc));
                Directory.SetLastWriteTimeUtc(localSubDirectory1,
                                              new DateTime(2014, 6, 12, 13, 2, 44, DateTimeKind.Utc));
                // create empty subdirectory
                Directory.CreateDirectory(localSubDirectory2);
                Directory.SetLastWriteTimeUtc(localSubDirectory2,
                                              new DateTime(2011, 5, 14, 1, 5, 12, DateTimeKind.Utc));
                Directory.SetLastWriteTimeUtc(localDirectory, new DateTime(2015, 10, 14, 22, 45, 11, DateTimeKind.Utc));
                using (var client = new ScpClient(_connectionInfoFactory.Create()))
                {
                    if (remotePathTransformation != null)
                    {
                        client.RemotePathTransformation = remotePathTransformation;
                    }
                    client.Connect();
                    client.Upload(new DirectoryInfo(localDirectory), remoteDirectory);
                }
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    Assert.IsTrue(client.Exists(remoteDirectory));
                    var remoteSftpDirectory = client.Get(remoteDirectory);
                    Assert.IsNotNull(remoteSftpDirectory);
                    Assert.AreEqual(absoluteRemoteDirectory, remoteSftpDirectory.FullName);
                    Assert.IsTrue(remoteSftpDirectory.IsDirectory);
                    Assert.IsFalse(remoteSftpDirectory.IsRegularFile);
                    // Due to CVE-2018-20685, we can no longer set the times or modes on a file or directory
                    // that refers to the current directory ('.'), the parent directory ('..') or a directory
                    // containing a forward slash ('/').
                    Assert.AreNotEqual(Directory.GetLastWriteTimeUtc(localDirectory), remoteSftpDirectory.LastWriteTimeUtc);
                    Assert.IsTrue(client.Exists(remotePathFile1));
                    Assert.AreEqual(CreateFileHash(localPathFile1), CreateRemoteFileHash(client, remotePathFile1));
                    var remoteSftpFile = client.Get(remotePathFile1);
                    Assert.IsNotNull(remoteSftpFile);
                    Assert.IsFalse(remoteSftpFile.IsDirectory);
                    Assert.IsTrue(remoteSftpFile.IsRegularFile);
                    Assert.AreEqual(File.GetLastWriteTimeUtc(localPathFile1), remoteSftpFile.LastWriteTimeUtc);
                    Assert.IsTrue(client.Exists(remotePathFile2));
                    Assert.AreEqual(CreateFileHash(localPathFile2), CreateRemoteFileHash(client, remotePathFile2));
                    remoteSftpFile = client.Get(remotePathFile2);
                    Assert.IsNotNull(remoteSftpFile);
                    Assert.IsFalse(remoteSftpFile.IsDirectory);
                    Assert.IsTrue(remoteSftpFile.IsRegularFile);
                    Assert.AreEqual(File.GetLastWriteTimeUtc(localPathFile2), remoteSftpFile.LastWriteTimeUtc);
                    Assert.IsTrue(client.Exists(remoteSubDirectory1));
                    remoteSftpDirectory = client.Get(remoteSubDirectory1);
                    Assert.IsNotNull(remoteSftpDirectory);
                    Assert.AreEqual(absoluteRemoteSubDirectory1, remoteSftpDirectory.FullName);
                    Assert.IsTrue(remoteSftpDirectory.IsDirectory);
                    Assert.IsFalse(remoteSftpDirectory.IsRegularFile);
                    Assert.AreEqual(Directory.GetLastWriteTimeUtc(localSubDirectory1), remoteSftpDirectory.LastWriteTimeUtc);
                    Assert.IsTrue(client.Exists(remotePathSubFile1));
                    Assert.AreEqual(CreateFileHash(localPathSubFile1), CreateRemoteFileHash(client, remotePathSubFile1));
                    Assert.IsTrue(client.Exists(remotePathSubFile2));
                    Assert.AreEqual(CreateFileHash(localPathSubFile2), CreateRemoteFileHash(client, remotePathSubFile2));
                    Assert.IsTrue(client.Exists(remoteSubDirectory2));
                    remoteSftpDirectory = client.Get(remoteSubDirectory2);
                    Assert.IsNotNull(remoteSftpDirectory);
                    Assert.AreEqual(absoluteRemoteSubDirectory2, remoteSftpDirectory.FullName);
                    Assert.IsTrue(remoteSftpDirectory.IsDirectory);
                    Assert.IsFalse(remoteSftpDirectory.IsRegularFile);
                    Assert.AreEqual(Directory.GetLastWriteTimeUtc(localSubDirectory2), remoteSftpDirectory.LastWriteTimeUtc);
                }
            }
            finally
            {
                Directory.Delete(localDirectory, true);
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    if (client.Exists(remotePathSubFile1))
                    {
                        client.DeleteFile(remotePathSubFile1);
                    }
                    if (client.Exists(remotePathSubFile2))
                    {
                        client.DeleteFile(remotePathSubFile2);
                    }
                    if (client.Exists(remoteSubDirectory1))
                    {
                        client.DeleteDirectory(remoteSubDirectory1);
                    }
                    if (client.Exists(remoteSubDirectory2))
                    {
                        client.DeleteDirectory(remoteSubDirectory2);
                    }
                    if (client.Exists(remotePathFile1))
                    {
                        client.DeleteFile(remotePathFile1);
                    }
                    if (client.Exists(remotePathFile2))
                    {
                        client.DeleteFile(remotePathFile2);
                    }
                    if (remoteDirectory.Length > 0 && remoteDirectory != "." && remoteDirectory != client.WorkingDirectory)
                    {
                        if (client.Exists(remoteDirectory))
                        {
                            client.DeleteDirectory(remoteDirectory);
                        }
                    }
                }
            }
        }
        [TestMethod]
        [DynamicData(nameof(GetScpUploadDirectoryInfoExistingFileData), DynamicDataSourceType.Method)]
        public void Scp_Upload_DirectoryInfo_ExistingFile(IRemotePathTransformation remotePathTransformation,
                                                          string remoteDirectory)
        {
            var remotePathFile1 = CombinePaths(remoteDirectory, "file1");
            var remotePathFile2 = CombinePaths(remoteDirectory, "file2");
            using (var client = new SshClient(_connectionInfoFactory.Create()))
            {
                client.Connect();
                Console.WriteLine(client.ConnectionInfo.CurrentKeyExchangeAlgorithm);
                using (var command = client.CreateCommand("rm -Rf " + _remotePathTransformation.Transform(remoteDirectory)))
                {
                    command.Execute();
                }
            }
            var localDirectory = Path.GetTempFileName();
            File.Delete(localDirectory);
            Directory.CreateDirectory(localDirectory);
            var localPathFile1 = Path.Combine(localDirectory, "file1");
            var localPathFile2 = Path.Combine(localDirectory, "file2");
            try
            {
                CreateFile(localPathFile1, 50);
                CreateFile(localPathFile2, 50);
                using (var client = new ScpClient(_connectionInfoFactory.Create()))
                {
                    if (remotePathTransformation != null)
                    {
                        client.RemotePathTransformation = remotePathTransformation;
                    }
                    client.Connect();
                    CreateRemoteFile(client, remoteDirectory, 10);
                    try
                    {
                        client.Upload(new DirectoryInfo(localDirectory), remoteDirectory);
                        Assert.Fail();
                    }
                    catch (ScpException ex)
                    {
                        Assert.IsNull(ex.InnerException);
                        Assert.AreEqual($"scp: {remoteDirectory}: Not a directory", ex.Message);
                    }
                }
            }
            finally
            {
                Directory.Delete(localDirectory, true);
                using (var client = new SftpClient(_connectionInfoFactory.Create()))
                {
                    client.Connect();
                    if (client.Exists(remotePathFile1))
                    {
                        client.DeleteFile(remotePathFile1);
                    }
                    if (client.Exists(remotePathFile2))
                    {
                        client.DeleteFile(remotePathFile2);
                    }
                    if (client.Exists((remoteDirectory)))
                    {
                        client.DeleteFile(remoteDirectory);
                    }
                }
            }
        }
        private static IEnumerable