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