diff --git a/Renci.SshClient/Local.testsettings b/Renci.SshClient/Local.testsettings new file mode 100644 index 00000000..af7cb9d6 --- /dev/null +++ b/Renci.SshClient/Local.testsettings @@ -0,0 +1,10 @@ + + + These are default test settings for a local test run. + + + + + + + \ No newline at end of file diff --git a/Renci.SshClient/Renci.SshClient.Test/Program.cs b/Renci.SshClient/Renci.SshClient.Test/Program.cs new file mode 100644 index 00000000..4bd6f4a3 --- /dev/null +++ b/Renci.SshClient/Renci.SshClient.Test/Program.cs @@ -0,0 +1,356 @@ +using System; +using System.IO; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Renci.SshClient.Test +{ + class Program + { + static void Main(string[] args) + { + + //var compressed1950 = new byte[] { 0x78, 0x9c, 0x62, 0x64, 0x60, 0x60, 0x60, 0x02, 0x62, 0xf1, 0x80, 0xc4, 0xe4, 0xec, 0xd4, 0x12, 0x85, 0xcc, 0xbc, 0x92, 0xd4, 0xf4, 0xa2, 0xcc, 0x92, 0x4a, 0x85, 0xd4, 0xa2, 0xa2, 0xfc, 0x22, 0x3d, 0xa0, 0x14, 0x03, 0x40 }; + //var compressed1951 = new byte[] { 0x62, 0x64, 0x60, 0x60, 0x60, 0x02, 0x62, 0xf1, 0x80, 0xc4, 0xe4, 0xec, 0xd4, 0x12, 0x85, 0xcc, 0xbc, 0x92, 0xd4, 0xf4, 0xa2, 0xcc, 0x92, 0x4a, 0x85, 0xd4, 0xa2, 0xa2, 0xfc, 0x22, 0x3d, 0xa0, 0x14, 0x03, 0x40 }; + //var uncompressed = new byte[] { 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x17, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x69, 0x74, 0x79, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2e, 0x00, 0x00, 0x00, 0x00 }; + //var uncompressed = "ABCDEFG".GetSshBytes().ToArray(); + + //var data = new byte[] { 87, 105, 107, 105, 112, 101, 100, 105, 97 }; + //var aa = CompressionZlib.Adler32(uncompressed); + ////8f da 08 ea + //var a1 = (byte)((aa & 0xFF000000) >> 24); + //var a2 = (byte)((aa & 0x00FF0000) >> 16); + //var a3 = (byte)((aa & 0x0000FF00) >> 8); + //var a4 = (byte)((aa & 0x000000FF) >> 0); + //Console.WriteLine("{0:x2} {1:x2} {2:x2} {3:x2} ", a1, a2, a3, a4); + + //byte[] result1 = null; + //using (var output = new MemoryStream()) + //{ + // using (var input = new MemoryStream(uncompressed)) + // using (var compress = new DeflateStream(output, CompressionMode.Compress)) + // { + // compress.FlushMode = FlushType.Partial; + // // Copy the source file into + // // the compression stream. + // input.CopyTo(compress); + + // result1 = output.ToArray(); + // } + //} + //result1.DebugPrint(); + + //byte[] result11 = null; + //using (var output = new MemoryStream()) + //{ + // using (var input = new MemoryStream(uncompressed)) + // using (var compress = new System.IO.Compression.DeflateStream(output, System.IO.Compression.CompressionMode.Compress)) + // { + // // Copy the source file into + // // the compression stream. + // input.CopyTo(compress); + + // result11 = output.ToArray(); + // } + //} + //result11.DebugPrint(); + + //byte[] result2 = null; + //using (var output = new MemoryStream()) + //{ + // using (var decompress = new DeflateStream(new MemoryStream(result1), CompressionMode.Decompress)) + // { + // // Copy the decompression stream + // // into the output file. + // decompress.CopyTo(output); + // result2 = output.ToArray(); + // } + //} + + //CompressionZlib c = new CompressionZlib(); + + //var d = new byte[] { 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65 }; + //var rr = c.Deflate(d); + //var b = c.Inflate(rr); + + //var baseFile = @"D:\small.txt"; + //var inFile = new FileInfo(string.Format("{0}", baseFile)); + //var outFile = new FileInfo(string.Format("{0}.gz", baseFile)); + //Compress(inFile.OpenRead(), outFile.Create()); + //var f = File.Create(string.Format("{0}.txt", baseFile)); + //Decompress(outFile.OpenRead(), f); + //f.Close(); + + //using (var file = File.OpenWrite("D:\\zerobunary.dat")) + //{ + // for (int j = 0; j < 10; j++) + // { + // for (int i = 0; i < 1024 * 1024 * 1024; i++) + // { + // file.WriteByte(0); + // } + // } + //} + + //TestSftp(); + //TestSftpDownload(); + + + //var shell = CreateShell(); + //shell.Connect(); + //var res = shell.Execute("ls -l"); + //shell.Disconnect(); + //Console.WriteLine(DateTime.Now + ":" + res.Length); + //res = shell.Execute("ls -l"); + //Console.WriteLine(DateTime.Now + ":" + res.Length); + //res = shell.Execute("ls -l"); + //Console.WriteLine(DateTime.Now + ":" + res.Length); + //shell.Disconnect(); + + //for (int i = 0; i < 2; i++) + //{ + // TestExec(i); + //} + + + // Parallel testing + var startTick = DateTime.Now.Ticks; + TestParallelConnections(); + //TestParallelExec(); + var endTick = DateTime.Now.Ticks; + //TestParallelAynchExec(); + + //s.Disconnect(); + Console.WriteLine("Finished in " + ((double)(endTick - startTick) / 10000000)); + Console.ReadKey(); + } + + private static volatile int _counter = 0; + + private static volatile int _errors = 0; + + private static volatile int _connectionCount; + + private static void TestParallelExec() + { + var shell = CreateShell(); + int _threadsCount = 0; + + System.Threading.Tasks.Parallel.For(0, 100, + new ParallelOptions + { + MaxDegreeOfParallelism = 15 + }, + () => + { + _threadsCount++; + return new object(); + }, + (int counter, ParallelLoopState pls, object conn) => + //(counter) => + //for (int counter = 0; counter < 100; counter++) + { + try + { + var result = EchoTest(shell, counter); + if (result == false) + { + _errors++; + } + Console.WriteLine("{5:000}: {4}: Count: {3:000}, Thread: {0:000}, i: {1:0000}, Result: {2:000000}", Thread.CurrentThread.ManagedThreadId, counter, result, _counter++, DateTime.Now, _threadsCount); + } + catch (Exception exp) + { + Console.WriteLine("{5:000}: {4}: Count: {3:000}, Thread: {0:000}, i: {1:0000}, Error: {2:000000}", Thread.CurrentThread.ManagedThreadId, counter, exp.Message, _counter++, DateTime.Now, _threadsCount); + _errors++; + } + return null; + }, + (object conn) => + { + _threadsCount--; + } + ); + + shell.Disconnect(); + + Console.WriteLine("Parallel execution tested"); + //Console.ReadKey(); + } + + private static void TestParallelAynchExec() + { + var shell = CreateShell(); + + System.Threading.Tasks.Parallel.For(0, 100000, + new ParallelOptions + { + MaxDegreeOfParallelism = 10 + }, + (counter) => + { + try + { + MemoryStream result = new MemoryStream(); + //var asyncResult = shell.BeginExecute("cat bigtestfile.txt", result, null, null); + var asyncResult = shell.BeginExecute("ls -l", result, null, null); + + asyncResult.AsyncWaitHandle.WaitOne(); + + shell.EndExecute(asyncResult); + + var r = Encoding.ASCII.GetString(result.ToArray()); + + Console.WriteLine("{4}: Count: {3:000}, Thread: {0:000}, i: {1:000}, Bytes: {2:000000}", Thread.CurrentThread.ManagedThreadId, counter, r.Length, _counter++, DateTime.Now); + } + catch (Exception exp) + { + Console.WriteLine("{4}: Count: {3:000}, Thread: {0:000}, i: {1:000}, Error: {2:000000}", Thread.CurrentThread.ManagedThreadId, counter, exp.Message, _counter++, DateTime.Now); + _errors++; + } + } + ); + + Console.WriteLine("Parallel execution tested"); + //Console.ReadKey(); + } + + private static void TestParallelConnections() + { + System.Threading.Tasks.Parallel.For(0, 10000, + new ParallelOptions + { + MaxDegreeOfParallelism = 10 + }, + () => + { + var conn = CreateShell(); + conn.Connect(); + _connectionCount++; + return conn; + }, + (int counter, ParallelLoopState pls, Shell conn) => + //(int counter) => + { + + //var conn = new Shell("152.54.9.105", 22, "oleg", "Maya1kap@"); + //conn.Connect(); + //_connectionCount++; + + StringBuilder sb = new StringBuilder(); + sb.AppendFormat("{0}", DateTime.Now); + sb.AppendFormat("Conn: {0:000} ", _connectionCount); + sb.AppendFormat("Thread: {0:000} ", Thread.CurrentThread.ManagedThreadId); + sb.AppendFormat("Count: {0:0000} ", _counter++); + sb.AppendFormat("i: {0:0000} ", counter); + try + { + + var result = EchoTest(conn, counter); + if (result == false) + { + _errors++; + } + + //var r = conn.Execute("cat bigtestfile.txt"); + //sb.AppendFormat("Bytes: {0:000000} ", r.Length); + sb.AppendFormat("Bytes: {0:000000} ", result); + } + catch (Exception exp) + { + sb.AppendFormat("Error: {0}", exp.Message); + _errors++; + } + Console.WriteLine(sb.ToString()); + + //conn.Disconnect(); + //_connectionCount--; + + return conn; + }, + (Shell conn) => + { + conn.Disconnect(); + _connectionCount--; + } + ); + + Console.WriteLine("Parallel execution tested"); + + //Console.ReadKey(); + } + + private static void TestSftpDownload() + { + Sftp sftp = new Sftp("152.54.8.155", 2222, "oleg", "Maya1kap@"); + sftp.DownloadFile("/home/oleg/uploadedfile.txt", @"D:\downloadtext1.txt"); + Console.WriteLine("SFTP tested."); + Console.ReadKey(); + } + + private static void TestSftp() + { + Sftp sftp = new Sftp("152.54.9.105", 2222, "oleg", "Maya1kap@"); + //sftp.UploadFile(@"D:\NoaaGetCapabilities.xml", "/home/oleg/uploadedfile.txt"); + sftp.UploadFile(@"D:\zerobunary.dat", "/home/oleg/uploadedfile.txt"); + sftp.UploadFile(@"D:\SQL Server Data\BCFS_0.ldf", "/home/oleg/uploadedfile.txt"); + + sftp.DownloadFile("/home/oleg/uploadedfile.txt", @"D:\downloadtext1.txt"); + + Console.WriteLine("SFTP tested."); + } + + private static void TestExec(int counter) + { + var s = CreateShell(); + s.Connect(); + MemoryStream debugStream = new MemoryStream(); + + //var res1 = s.Execute("cat bigtestfile.txt", debugStream); + //var res2 = Encoding.ASCII.GetString(debugStream.ToArray()); + var result = EchoTest(s, counter); + + + Console.WriteLine("{4}: Count: {3:000}, Thread: {0:000}, i: {1:000}, Bytes: {2:000000}", Thread.CurrentThread.ManagedThreadId, counter, result, _counter++, DateTime.Now); + s.Disconnect(); + + //Console.WriteLine("Execute tested."); + //Console.ReadKey(); + } + + private static bool EchoTest(Shell shell, int counter) + { + bool result; + var length = 1024 * 16; + var btf = shell.Execute(string.Format("for i in {{1..{0}}}\ndo\necho \"ABCDEFG\"\ndone\n", length / 8)); + + result = (btf.Length == length); + if (!result) + return result; + + var r = shell.Execute(string.Format("echo {0}", counter)); + int r1; + if (int.TryParse(r, out r1)) + { + result = (r1 == counter); + } + else + { + result = false; + } + + //shell.Execute("sleep 10"); + + return result; + } + + private static Shell CreateShell() + { + return new Shell("152.54.8.155", 22, "oleg", "Maya1kap@"); + //return new Shell("152.54.8.155", 22, "oleg", "Maya1kap@"); + //return new Shell("br0.renci.org", 22, "wrf", new PrivateKeyFile(@"H:\My Documents\SSHKeys\useme.key")); + } + + } +} diff --git a/Renci.SshClient/Renci.SshClient.Test/Properties/AssemblyInfo.cs b/Renci.SshClient/Renci.SshClient.Test/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..d5f617b5 --- /dev/null +++ b/Renci.SshClient/Renci.SshClient.Test/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Renci.SshClient.Test")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("Renci.SshClient.Test")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2010")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("5d878689-525b-444d-8e7e-4500e0eebd64")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Renci.SshClient/Renci.SshClient.Test/Renci.SshClient.Test.csproj b/Renci.SshClient/Renci.SshClient.Test/Renci.SshClient.Test.csproj new file mode 100644 index 00000000..5fced66c --- /dev/null +++ b/Renci.SshClient/Renci.SshClient.Test/Renci.SshClient.Test.csproj @@ -0,0 +1,84 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {23E84A34-A9EC-47D5-BECE-0725053BB17E} + Exe + Properties + Renci.SshClient.Test + Renci.SshClient.Test + v4.0 + Client + 512 + SAK + SAK + SAK + SAK + + + x86 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x86\DebugNoTimeout\ + DEBUG;TRACE + full + x86 + bin\Debug\Renci.SshClient.Test.exe.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + false + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + false + + + + + + + + + + + + + + + + + + {2F5F8C90-0BD1-424F-997C-7BC6280919D1} + Renci.SshClient + + + + + \ No newline at end of file diff --git a/Renci.SshClient/Renci.SshClient.Test/Renci.SshClient.Test.csproj.vspscc b/Renci.SshClient/Renci.SshClient.Test/Renci.SshClient.Test.csproj.vspscc new file mode 100644 index 00000000..feffdeca --- /dev/null +++ b/Renci.SshClient/Renci.SshClient.Test/Renci.SshClient.Test.csproj.vspscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "" +"NUMBER_OF_EXCLUDED_FILES" = "0" +"ORIGINAL_PROJECT_FILE_PATH" = "" +"NUMBER_OF_NESTED_PROJECTS" = "0" +"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER" +} diff --git a/Renci.SshClient/Renci.SshClient.sln b/Renci.SshClient/Renci.SshClient.sln index b77f7f56..a8d247ff 100644 --- a/Renci.SshClient/Renci.SshClient.sln +++ b/Renci.SshClient/Renci.SshClient.sln @@ -3,7 +3,14 @@ Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Renci.SshClient", "Renci.SshClient\Renci.SshClient.csproj", "{2F5F8C90-0BD1-424F-997C-7BC6280919D1}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Renci.SshClient.Test", "Renci.SshClient.Test\Renci.SshClient.Test.csproj", "{23E84A34-A9EC-47D5-BECE-0725053BB17E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Renci.SshClient.Tests", "Tests\Renci.SshClient.Tests.csproj", "{C45379B9-17B1-4E89-BC2E-6D41726413E8}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A3063E62-89D5-43FF-AB1A-FFBECB4A1850}" + ProjectSection(SolutionItems) = preProject + Local.testsettings = Local.testsettings + Renci.SshClient1.vsmdi = Renci.SshClient1.vsmdi + TraceAndTestImpact.testsettings = TraceAndTestImpact.testsettings + EndProjectSection EndProject Global GlobalSection(TeamFoundationVersionControl) = preSolution @@ -11,12 +18,15 @@ Global SccEnterpriseProvider = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C} SccTeamFoundationServer = https://tfs.codeplex.com/tfs/tfs11 SccLocalPath0 = . - SccProjectUniqueName1 = Renci.SshClient.Test\\Renci.SshClient.Test.csproj - SccProjectName1 = Renci.SshClient.Test - SccLocalPath1 = Renci.SshClient.Test - SccProjectUniqueName2 = Renci.SshClient\\Renci.SshClient.csproj - SccProjectName2 = Renci.SshClient - SccLocalPath2 = Renci.SshClient + SccProjectUniqueName1 = Renci.SshClient\\Renci.SshClient.csproj + SccProjectName1 = Renci.SshClient + SccLocalPath1 = Renci.SshClient + SccProjectUniqueName2 = Tests\\Renci.SshClient.Tests.csproj + SccProjectName2 = Tests + SccLocalPath2 = Tests + EndGlobalSection + GlobalSection(TestCaseManagementSettings) = postSolution + CategoryFile = Renci.SshClient1.vsmdi EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -45,21 +55,21 @@ Global {2F5F8C90-0BD1-424F-997C-7BC6280919D1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {2F5F8C90-0BD1-424F-997C-7BC6280919D1}.Release|Mixed Platforms.Build.0 = Release|Any CPU {2F5F8C90-0BD1-424F-997C-7BC6280919D1}.Release|x86.ActiveCfg = Release|Any CPU - {23E84A34-A9EC-47D5-BECE-0725053BB17E}.Debug|Any CPU.ActiveCfg = Debug|x86 - {23E84A34-A9EC-47D5-BECE-0725053BB17E}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {23E84A34-A9EC-47D5-BECE-0725053BB17E}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {23E84A34-A9EC-47D5-BECE-0725053BB17E}.Debug|x86.ActiveCfg = Debug|x86 - {23E84A34-A9EC-47D5-BECE-0725053BB17E}.Debug|x86.Build.0 = Debug|x86 - {23E84A34-A9EC-47D5-BECE-0725053BB17E}.DebugNoTimeout|Any CPU.ActiveCfg = DebugNoTimeout|x86 - {23E84A34-A9EC-47D5-BECE-0725053BB17E}.DebugNoTimeout|Mixed Platforms.ActiveCfg = DebugNoTimeout|x86 - {23E84A34-A9EC-47D5-BECE-0725053BB17E}.DebugNoTimeout|Mixed Platforms.Build.0 = DebugNoTimeout|x86 - {23E84A34-A9EC-47D5-BECE-0725053BB17E}.DebugNoTimeout|x86.ActiveCfg = DebugNoTimeout|x86 - {23E84A34-A9EC-47D5-BECE-0725053BB17E}.DebugNoTimeout|x86.Build.0 = DebugNoTimeout|x86 - {23E84A34-A9EC-47D5-BECE-0725053BB17E}.Release|Any CPU.ActiveCfg = Release|x86 - {23E84A34-A9EC-47D5-BECE-0725053BB17E}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {23E84A34-A9EC-47D5-BECE-0725053BB17E}.Release|Mixed Platforms.Build.0 = Release|x86 - {23E84A34-A9EC-47D5-BECE-0725053BB17E}.Release|x86.ActiveCfg = Release|x86 - {23E84A34-A9EC-47D5-BECE-0725053BB17E}.Release|x86.Build.0 = Release|x86 + {C45379B9-17B1-4E89-BC2E-6D41726413E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C45379B9-17B1-4E89-BC2E-6D41726413E8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C45379B9-17B1-4E89-BC2E-6D41726413E8}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {C45379B9-17B1-4E89-BC2E-6D41726413E8}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {C45379B9-17B1-4E89-BC2E-6D41726413E8}.Debug|x86.ActiveCfg = Debug|Any CPU + {C45379B9-17B1-4E89-BC2E-6D41726413E8}.DebugNoTimeout|Any CPU.ActiveCfg = Debug|Any CPU + {C45379B9-17B1-4E89-BC2E-6D41726413E8}.DebugNoTimeout|Any CPU.Build.0 = Debug|Any CPU + {C45379B9-17B1-4E89-BC2E-6D41726413E8}.DebugNoTimeout|Mixed Platforms.ActiveCfg = Debug|Any CPU + {C45379B9-17B1-4E89-BC2E-6D41726413E8}.DebugNoTimeout|Mixed Platforms.Build.0 = Debug|Any CPU + {C45379B9-17B1-4E89-BC2E-6D41726413E8}.DebugNoTimeout|x86.ActiveCfg = Debug|Any CPU + {C45379B9-17B1-4E89-BC2E-6D41726413E8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C45379B9-17B1-4E89-BC2E-6D41726413E8}.Release|Any CPU.Build.0 = Release|Any CPU + {C45379B9-17B1-4E89-BC2E-6D41726413E8}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {C45379B9-17B1-4E89-BC2E-6D41726413E8}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {C45379B9-17B1-4E89-BC2E-6D41726413E8}.Release|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Renci.SshClient/Renci.SshClient1.vsmdi b/Renci.SshClient/Renci.SshClient1.vsmdi new file mode 100644 index 00000000..040279c4 --- /dev/null +++ b/Renci.SshClient/Renci.SshClient1.vsmdi @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Renci.SshClient/Tests/ConnectionData.cs b/Renci.SshClient/Tests/ConnectionData.cs new file mode 100644 index 00000000..d6eca877 --- /dev/null +++ b/Renci.SshClient/Tests/ConnectionData.cs @@ -0,0 +1,18 @@ + +namespace Renci.SshClient.Tests +{ + public static class ConnectionData + { + public static string Host { get { return "you host here"; } } + + public static int Port { get { return 22; } } + + public static string Username { get { return "username"; } } + + public static string Password { get { return "password@"; } } + + public static string RsaKeyFilePath { get { return @"path to rsa key file"; } } + + public static string DssKeyFilePath { get { return @"path to dss key file"; } } + } +} diff --git a/Renci.SshClient/Tests/Properties/AssemblyInfo.cs b/Renci.SshClient/Tests/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..9fd18268 --- /dev/null +++ b/Renci.SshClient/Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("Tests")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2010")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("defb66b2-a4b9-40ca-b205-2183d84b7323")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Renci.SshClient/Tests/Renci.SshClient.Tests.csproj b/Renci.SshClient/Tests/Renci.SshClient.Tests.csproj new file mode 100644 index 00000000..d8a31090 --- /dev/null +++ b/Renci.SshClient/Tests/Renci.SshClient.Tests.csproj @@ -0,0 +1,74 @@ + + + + Debug + AnyCPU + + + 2.0 + {C45379B9-17B1-4E89-BC2E-6D41726413E8} + Library + Properties + Renci.SshClient.Tests + Renci.SshClient.Tests + v4.0 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + SAK + SAK + SAK + SAK + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + 3.5 + + + + + False + + + + + + + + + + {2F5F8C90-0BD1-424F-997C-7BC6280919D1} + Renci.SshClient + + + + + \ No newline at end of file diff --git a/Renci.SshClient/Tests/Renci.SshClient.Tests.csproj.vspscc b/Renci.SshClient/Tests/Renci.SshClient.Tests.csproj.vspscc new file mode 100644 index 00000000..feffdeca --- /dev/null +++ b/Renci.SshClient/Tests/Renci.SshClient.Tests.csproj.vspscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "" +"NUMBER_OF_EXCLUDED_FILES" = "0" +"ORIGINAL_PROJECT_FILE_PATH" = "" +"NUMBER_OF_NESTED_PROJECTS" = "0" +"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER" +} diff --git a/Renci.SshClient/Tests/ShellTest.cs b/Renci.SshClient/Tests/ShellTest.cs new file mode 100644 index 00000000..308d079c --- /dev/null +++ b/Renci.SshClient/Tests/ShellTest.cs @@ -0,0 +1,251 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Text; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Renci.SshClient.Common; + +namespace Renci.SshClient.Tests +{ + /// + /// Summary description for UnitTest1 + /// + [TestClass] + public class ShellTest + { + public ShellTest() + { + // + // TODO: Add constructor logic here + // + } + + private TestContext testContextInstance; + + /// + ///Gets or sets the test context which provides + ///information about and functionality for the current test run. + /// + public TestContext TestContext + { + get + { + return testContextInstance; + } + set + { + testContextInstance = value; + } + } + + #region Additional test attributes + // + // You can use the following additional attributes as you write your tests: + // + // Use ClassInitialize to run code before running the first test in the class + // [ClassInitialize()] + // public static void MyClassInitialize(TestContext testContext) { } + // + // Use ClassCleanup to run code after all tests in a class have run + // [ClassCleanup()] + // public static void MyClassCleanup() { } + // + // Use TestInitialize to run code before running each test + // [TestInitialize()] + // public void MyTestInitialize() { } + // + // Use TestCleanup to run code after each test has run + // [TestCleanup()] + // public void MyTestCleanup() { } + // + #endregion + + [TestMethod] + public void TestConnectUsingPassword() + { + var s = CreateShellUsingPassword(); + s.Connect(); + s.Disconnect(); + } + + [TestMethod] + public void TestExecuteSingleCommand() + { + var s = CreateShellUsingPassword(); + s.Connect(); + var result = ExecuteTestCommand(s); + s.Disconnect(); + + Assert.IsTrue(result); + } + + [TestMethod] + public void TestReconnecting() + { + var s = CreateShellUsingPassword(); + s.Connect(); + var result = ExecuteTestCommand(s); + s.Disconnect(); + + Assert.IsTrue(result); + + s.Connect(); + result = ExecuteTestCommand(s); + s.Disconnect(); + + Assert.IsTrue(result); + } + + [TestMethod] + public void TestMultipleThreadMultipleSessions_10000() + { + var s = CreateShellUsingPassword(); + + System.Threading.Tasks.Parallel.For(0, 10000, + (counter) => + { + var result = ExecuteTestCommand(s); + Assert.IsTrue(result); + } + ); + + s.Disconnect(); + } + + [TestMethod] + public void TestMultipleThreadMultipleConnections_10000() + { + try + { + + System.Threading.Tasks.Parallel.For(0, 10000, + new ParallelOptions + { + MaxDegreeOfParallelism = 1, + }, + () => + { + var s = CreateShellUsingPassword(); + s.Connect(); + return s; + }, + (int counter, ParallelLoopState pls, Shell s) => + { + var result = ExecuteTestCommand(s); + Debug.WriteLine(string.Format("TestMultipleThreadMultipleConnections #{0}", counter)); + Assert.IsTrue(result); + return s; + }, + (Shell s) => + { + s.Disconnect(); + } + ); + } + catch (Exception exp) + { + Assert.Fail(exp.ToString()); + } + } + + [TestMethod] + public void TestExtendedOutput() + { + var s = CreateShellUsingPassword(); + MemoryStream ms = new MemoryStream(); + s.Connect(); + var result = s.Execute("echo 12345; echo 654321 >&2", ms); + var extendedData = Encoding.ASCII.GetString(ms.ToArray()); + result = result.Substring(0, result.Length - 1); // Remove \n chararacter returned by command + extendedData = extendedData.Substring(0, extendedData.Length - 1); // Remove \n chararacter returned by command + s.Disconnect(); + + Assert.AreEqual("12345", result); + Assert.AreEqual("654321", extendedData); + } + + [TestMethod] + public void TestInvalidCommandExecution() + { + var s = CreateShellUsingPassword(); + s.Connect(); + try + { + s.Execute(";"); + Assert.Fail("Operation should fail"); + } + catch (SshException exp) + { + Assert.AreEqual(exp.ExitStatus, (uint)2); + } + s.Disconnect(); + } + + [TestMethod] + public void TestInvalidCommandThenValidCommandExecution() + { + var s = CreateShellUsingPassword(); + s.Connect(); + try + { + s.Execute(";"); + Assert.Fail("Operation should fail"); + } + catch (SshException exp) + { + Assert.AreEqual(exp.ExitStatus, (uint)2); + } + var result = ExecuteTestCommand(s); + s.Disconnect(); + + Assert.IsTrue(result); + } + + [TestMethod] + public void TestRsaKeyConnection() + { + var s = CreateShellUsingRSAKey(); + s.Connect(); + var result = ExecuteTestCommand(s); + s.Disconnect(); + Assert.IsTrue(result); + } + + [TestMethod] + public void TestDssKeyConnection() + { + var s = CreateShellUsingRSAKey(); + s.Connect(); + var result = ExecuteTestCommand(s); + s.Disconnect(); + Assert.IsTrue(result); + } + + private static Shell CreateShellUsingPassword() + { + return new Shell(ConnectionData.Host, ConnectionData.Port, ConnectionData.Username, ConnectionData.Password); + } + + private static Shell CreateShellUsingRSAKey() + { + return new Shell(ConnectionData.Host, ConnectionData.Port, ConnectionData.Username, new PrivateKeyFile(ConnectionData.RsaKeyFilePath)); + } + + private static Shell CreateShellUsingDSSKey() + { + return new Shell(ConnectionData.Host, ConnectionData.Port, ConnectionData.Username, new PrivateKeyFile(ConnectionData.DssKeyFilePath)); + } + + private static bool ExecuteTestCommand(Shell s) + { + var testValue = Guid.NewGuid().ToString(); + var command = string.Format("echo {0}", testValue); + var result = s.Execute(command); + result = result.Substring(0, result.Length - 1); // Remove \n chararacter returned by command + return result.Equals(testValue); + } + + + } +} diff --git a/Renci.SshClient/TraceAndTestImpact.testsettings b/Renci.SshClient/TraceAndTestImpact.testsettings new file mode 100644 index 00000000..7c80586f --- /dev/null +++ b/Renci.SshClient/TraceAndTestImpact.testsettings @@ -0,0 +1,21 @@ + + + These are test settings for Trace and Test Impact. + + + + + + + + + + + + + + + + + + \ No newline at end of file