Quellcode durchsuchen

ConnectionInfo.cs:235 - Removed ! infront of IsNullOrEmpty in final constructor.
Added alot of documentation.
Added alot of parameter checks.
Added alot of tests.

Kenneth_aa_cp vor 13 Jahren
Ursprung
Commit
25816b1dd7
32 geänderte Dateien mit 453 neuen und 23 gelöschten Zeilen
  1. 121 0
      Renci.SshClient/Renci.SshNet.Tests/AuthenticationMethodDerivativesTest.cs
  2. 146 12
      Renci.SshClient/Renci.SshNet.Tests/ConnectionTest.cs
  3. 5 0
      Renci.SshClient/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj
  4. 18 0
      Renci.SshClient/Renci.SshNet.Tests/Security/TestCipher.cs
  5. 10 0
      Renci.SshClient/Renci.SshNet.Tests/Security/TestKeyExchange.cs
  6. 19 5
      Renci.SshClient/Renci.SshNet.Tests/Security/TestPrivateKeyFile.cs
  7. 1 0
      Renci.SshClient/Renci.SshNet.Tests/SshClientTests/TestPortForwarding.cs
  8. 1 0
      Renci.SshClient/Renci.SshNet/AuthenticationMethod.cs
  9. 4 1
      Renci.SshClient/Renci.SshNet/ConnectionInfo.cs
  10. 14 0
      Renci.SshClient/Renci.SshNet/ExpectAction.cs
  11. 1 0
      Renci.SshClient/Renci.SshNet/KeyboardInteractiveAuthenticationMethod.NET40.cs
  12. 1 0
      Renci.SshClient/Renci.SshNet/KeyboardInteractiveAuthenticationMethod.cs
  13. 2 0
      Renci.SshClient/Renci.SshNet/KeyboardInteractiveConnectionInfo.cs
  14. 5 1
      Renci.SshClient/Renci.SshNet/MessageEventArgs.cs
  15. 4 0
      Renci.SshClient/Renci.SshNet/Messages/Connection/ChannelRequest/ExecRequestInfo.cs
  16. 5 0
      Renci.SshClient/Renci.SshNet/NetConfClient.cs
  17. 5 0
      Renci.SshClient/Renci.SshNet/NoneAuthenticationMethod.cs
  18. 1 0
      Renci.SshClient/Renci.SshNet/PasswordAuthenticationMethod.NET40.cs
  19. 2 0
      Renci.SshClient/Renci.SshNet/PasswordAuthenticationMethod.cs
  20. 2 0
      Renci.SshClient/Renci.SshNet/PrivateKeyAuthenticationMethod.cs
  21. 36 0
      Renci.SshClient/Renci.SshNet/ScpClient.NET.cs
  22. 2 0
      Renci.SshClient/Renci.SshNet/ScpClient.cs
  23. 1 0
      Renci.SshClient/Renci.SshNet/Session.cs
  24. 3 0
      Renci.SshClient/Renci.SshNet/Sftp/SftpFile.cs
  25. 5 0
      Renci.SshClient/Renci.SshNet/SftpClient.NET40.cs
  26. 14 0
      Renci.SshClient/Renci.SshNet/SftpClient.cs
  27. 1 0
      Renci.SshClient/Renci.SshNet/Shell.NET40.cs
  28. 4 4
      Renci.SshClient/Renci.SshNet/ShellStream.cs
  29. 14 0
      Renci.SshClient/Renci.SshNet/SshClient.cs
  30. 1 0
      Renci.SshClient/Renci.SshNet/SshCommand.NET40.cs
  31. 4 0
      Renci.SshClient/Renci.SshNet/SshCommand.cs
  32. 1 0
      Renci.SshClient/Renci.SshNet/SubsystemSession.cs

+ 121 - 0
Renci.SshClient/Renci.SshNet.Tests/AuthenticationMethodDerivativesTest.cs

@@ -0,0 +1,121 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Renci.SshNet.Common;
+
+namespace Renci.SshNet.Tests
+{
+    [TestClass]
+    public class AuthenticationMethodDerivativesTest
+    {
+        [TestMethod]
+        [TestCategory("AuthenticationMethod")]
+        [Owner("Kenneth_aa")]
+        [Description("KeyboardInteractiveAuthenticationMethod: Pass null as username.")]
+        [ExpectedException(typeof(ArgumentException))]
+        public void Keyboard_Test_Pass_Null()
+        {
+            new KeyboardInteractiveAuthenticationMethod(null);
+        }
+
+        [TestMethod]
+        [TestCategory("AuthenticationMethod")]
+        [Owner("Kenneth_aa")]
+        [Description("KeyboardInteractiveAuthenticationMethod: Pass String.Empty as username.")]
+        [ExpectedException(typeof(ArgumentException))]
+        public void Keyboard_Test_Pass_Whitespace()
+        {
+            new KeyboardInteractiveAuthenticationMethod(string.Empty);
+        }
+
+        [TestMethod]
+        [TestCategory("AuthenticationMethod")]
+        [Owner("Kenneth_aa")]
+        [Description("NoneAuthenticationMethod: Pass null as username.")]
+        [ExpectedException(typeof(ArgumentException))]
+        public void None_Test_Pass_Null()
+        {
+            new NoneAuthenticationMethod(null);
+        }
+
+        [TestMethod]
+        [TestCategory("AuthenticationMethod")]
+        [Owner("Kenneth_aa")]
+        [Description("NoneAuthenticationMethod: Pass String.Empty as username.")]
+        [ExpectedException(typeof(ArgumentException))]
+        public void None_Test_Pass_Whitespace()
+        {
+            new NoneAuthenticationMethod(string.Empty);
+        }
+
+        [TestMethod]
+        [TestCategory("AuthenticationMethod")]
+        [Owner("Kenneth_aa")]
+        [Description("PasswordAuthenticationMethod: Pass null as username, \"valid\" as password.")]
+        [ExpectedException(typeof(ArgumentException))]
+        public void Password_Test_Pass_Null_Username()
+        {
+            new PasswordAuthenticationMethod(null, "valid");
+        }
+
+        [TestMethod]
+        [TestCategory("AuthenticationMethod")]
+        [Owner("Kenneth_aa")]
+        [Description("PasswordAuthenticationMethod: Pass \"valid\" as username, null as password.")]
+        [ExpectedException(typeof(ArgumentNullException))]
+        public void Password_Test_Pass_Null_Password()
+        {
+            new PasswordAuthenticationMethod("valid", null);
+        }
+
+        [TestMethod]
+        [TestCategory("AuthenticationMethod")]
+        [Owner("Kenneth_aa")]
+        [Description("PasswordAuthenticationMethod: Pass \"valid\" as username, \"valid\" as password.")]
+        public void Password_Test_Pass_Valid_Username_And_Password()
+        {
+            new PasswordAuthenticationMethod("valid", "valid");
+        }
+
+        [TestMethod]
+        [TestCategory("AuthenticationMethod")]
+        [Owner("Kenneth_aa")]
+        [Description("PasswordAuthenticationMethod: Pass String.Empty as username, \"valid\" as password.")]
+        [ExpectedException(typeof(ArgumentException))]
+        public void Password_Test_Pass_Whitespace()
+        {
+            new PasswordAuthenticationMethod(string.Empty, "valid");
+        }
+
+        [TestMethod]
+        [TestCategory("AuthenticationMethod")]
+        [Owner("Kenneth_aa")]
+        [Description("PasswordAuthenticationMethod: Pass \"valid\" as username, String.Empty as password.")]
+        public void Password_Test_Pass_Valid()
+        {
+            new PasswordAuthenticationMethod("valid", string.Empty);
+        }
+
+        [TestMethod]
+        [TestCategory("AuthenticationMethod")]
+        [Owner("Kenneth_aa")]
+        [Description("PrivateKeyAuthenticationMethod: Pass null as username, null as password.")]
+        [ExpectedException(typeof(ArgumentException))]
+        public void PrivateKey_Test_Pass_Null()
+        {
+            new PrivateKeyAuthenticationMethod(null, null);
+        }
+
+        [TestMethod]
+        [TestCategory("AuthenticationMethod")]
+        [Owner("Kenneth_aa")]
+        [Description("PrivateKeyAuthenticationMethod: Pass String.Empty as username, null as password.")]
+        [ExpectedException(typeof(ArgumentException))]
+        public void PrivateKey_Test_Pass_Whitespace()
+        {
+            new PrivateKeyAuthenticationMethod(string.Empty, null);
+        }
+    }
+}

+ 146 - 12
Renci.SshClient/Renci.SshNet.Tests/ConnectionTest.cs

@@ -15,6 +15,7 @@ namespace Renci.SshNet.Tests
 	public class ConnectionTest
 	{
 		[TestMethod]
+        [TestCategory("Authentication")]
 		public void Test_Connect_Using_Correct_Password()
 		{
 			using (var client = new SshClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD))
@@ -24,7 +25,8 @@ namespace Renci.SshNet.Tests
 			}
 		}
 
-		[TestMethod]
+        [TestMethod]
+        [TestCategory("Authentication")]
 		[ExpectedException(typeof(SshAuthenticationException))]
 		public void Test_Connect_Using_Invalid_Password()
 		{
@@ -35,7 +37,8 @@ namespace Renci.SshNet.Tests
 			}
 		}
 
-		[TestMethod]
+        [TestMethod]
+        [TestCategory("Authentication")]
 		public void Test_Connect_Using_Rsa_Key_Without_PassPhrase()
 		{
 			MemoryStream keyFileStream = new MemoryStream(Encoding.ASCII.GetBytes(Resources.RSA_KEY_WITHOUT_PASS));
@@ -46,7 +49,8 @@ namespace Renci.SshNet.Tests
 			}
 		}
 
-		[TestMethod]
+        [TestMethod]
+        [TestCategory("Authentication")]
 		public void Test_Connect_Using_RsaKey_With_PassPhrase()
 		{
 			MemoryStream keyFileStream = new MemoryStream(Encoding.ASCII.GetBytes(Resources.RSA_KEY_WITH_PASS));
@@ -57,7 +61,8 @@ namespace Renci.SshNet.Tests
 			}
 		}
 
-		[TestMethod]
+        [TestMethod]
+        [TestCategory("Authentication")]
 		[ExpectedException(typeof(SshPassPhraseNullOrEmptyException))]
 		public void Test_Connect_Using_Key_With_Empty_PassPhrase()
 		{
@@ -69,7 +74,8 @@ namespace Renci.SshNet.Tests
 			}
 		}
 
-		[TestMethod]
+        [TestMethod]
+        [TestCategory("Authentication")]
 		public void Test_Connect_Using_DsaKey_Without_PassPhrase()
 		{
 			MemoryStream keyFileStream = new MemoryStream(Encoding.ASCII.GetBytes(Resources.DSA_KEY_WITHOUT_PASS));
@@ -80,7 +86,8 @@ namespace Renci.SshNet.Tests
 			}
 		}
 
-		[TestMethod]
+        [TestMethod]
+        [TestCategory("Authentication")]
 		public void Test_Connect_Using_DsaKey_With_PassPhrase()
 		{
 			MemoryStream keyFileStream = new MemoryStream(Encoding.ASCII.GetBytes(Resources.DSA_KEY_WITH_PASS));
@@ -91,7 +98,8 @@ namespace Renci.SshNet.Tests
 			}
 		}
 
-		[TestMethod]
+        [TestMethod]
+        [TestCategory("Authentication")]
 		[ExpectedException(typeof(SshAuthenticationException))]
 		public void Test_Connect_Using_Invalid_PrivateKey()
 		{
@@ -103,7 +111,8 @@ namespace Renci.SshNet.Tests
 			}
 		}
 
-		[TestMethod]
+        [TestMethod]
+        [TestCategory("Authentication")]
 		public void Test_Connect_Using_Multiple_PrivateKeys()
 		{
 			using (var client = new SshClient(Resources.HOST, Resources.USERNAME,
@@ -120,7 +129,8 @@ namespace Renci.SshNet.Tests
 		}
 
 
-		[TestMethod]
+        [TestMethod]
+        [TestCategory("Authentication")]
 		public void Test_Connect_Then_Reconnect()
 		{
 			using (var client = new SshClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD))
@@ -132,21 +142,24 @@ namespace Renci.SshNet.Tests
 			}
 		}
 
-		[WorkItem(703), TestMethod]
+        [WorkItem(703), TestMethod]
+        [TestCategory("PasswordConnectionInfo")]
 		[ExpectedException(typeof(ArgumentException))]
 		public void Test_ConnectionInfo_Host_Is_Null()
 		{
 			var connectionInfo = new PasswordConnectionInfo(null, "username", "password");
 		}
 
-		[WorkItem(703), TestMethod]
+        [WorkItem(703), TestMethod]
+        [TestCategory("PasswordConnectionInfo")]
 		[ExpectedException(typeof(ArgumentException))]
 		public void Test_ConnectionInfo_Username_Is_Null()
 		{
 			var connectionInfo = new PasswordConnectionInfo("host", null, "password");
 		}
 
-		[WorkItem(703), TestMethod]
+        [WorkItem(703), TestMethod]
+        [TestCategory("PasswordConnectionInfo")]
 		[ExpectedException(typeof(ArgumentNullException))]
 		public void Test_ConnectionInfo_Password_Is_Null()
 		{
@@ -154,6 +167,7 @@ namespace Renci.SshNet.Tests
 		}
 
 		[TestMethod]
+        [TestCategory("PasswordConnectionInfo")]
 		[Description("Test passing whitespace to host parameter.")]
 		[ExpectedException(typeof(ArgumentException))]
 		public void Test_ConnectionInfo_Host_Is_Whitespace()
@@ -162,6 +176,7 @@ namespace Renci.SshNet.Tests
 		}
 
 		[TestMethod]
+        [TestCategory("PasswordConnectionInfo")]
 		[Description("Test passing whitespace to username parameter.")]
 		[ExpectedException(typeof(ArgumentException))]
 		public void Test_ConnectionInfo_Username_Is_Whitespace()
@@ -170,6 +185,7 @@ namespace Renci.SshNet.Tests
 		}
 
 		[WorkItem(703), TestMethod]
+        [TestCategory("PasswordConnectionInfo")]
 		[ExpectedException(typeof(ArgumentOutOfRangeException))]
 		public void Test_ConnectionInfo_SmallPortNumber()
 		{
@@ -177,11 +193,129 @@ namespace Renci.SshNet.Tests
 		}
 
 		[WorkItem(703), TestMethod]
+        [TestCategory("PasswordConnectionInfo")]
 		[ExpectedException(typeof(ArgumentOutOfRangeException))]
 		public void Test_ConnectionInfo_BigPortNumber()
 		{
 			var connectionInfo = new PasswordConnectionInfo(Resources.HOST, IPEndPoint.MaxPort + 1, Resources.USERNAME, Resources.PASSWORD);
 		}
 
+        [TestMethod]
+        [TestCategory("ConnectionInfo")]
+        [Description("Pass null as proxy host.")]
+        [Owner("Kenneth_aa")]
+        [ExpectedException(typeof(ArgumentException))]
+        public void Test_ConnectionInfo_ProxyHost_Null()
+        {
+            new ConnectionInfo(Resources.HOST, 22, Resources.USERNAME, ProxyTypes.None, null, 22, Resources.USERNAME, Resources.PASSWORD, null);
+        }
+
+        [TestMethod]
+        [TestCategory("ConnectionInfo")]
+        [Description("Pass String.Empty as proxy host.")]
+        [Owner("Kenneth_aa")]
+        [ExpectedException(typeof(ArgumentException))]
+        public void Test_ConnectionInfo_ProxyHost_Empty()
+        {
+            new ConnectionInfo(Resources.HOST, 22, Resources.USERNAME, ProxyTypes.None, string.Empty, 22, Resources.USERNAME, Resources.PASSWORD, null);
+        }
+
+        [TestMethod]
+        [TestCategory("ConnectionInfo")]
+        [Description("Pass too large proxy port.")]
+        [Owner("Kenneth_aa")]
+        [ExpectedException(typeof(ArgumentOutOfRangeException))]
+        public void Test_ConnectionInfo_ProxyPort_Large()
+        {
+            new ConnectionInfo(Resources.HOST, 22, Resources.USERNAME, ProxyTypes.None, Resources.HOST, int.MaxValue, Resources.USERNAME, Resources.PASSWORD, null);
+        }
+
+        [TestMethod]
+        [TestCategory("ConnectionInfo")]
+        [Description("Pass too small proxy port.")]
+        [Owner("Kenneth_aa")]
+        [ExpectedException(typeof(ArgumentOutOfRangeException))]
+        public void Test_ConnectionInfo_ProxyPort_Small()
+        {
+            new ConnectionInfo(Resources.HOST, 22, Resources.USERNAME, ProxyTypes.None, Resources.HOST, int.MinValue, Resources.USERNAME, Resources.PASSWORD, null);
+        }
+
+        [TestMethod]
+        [TestCategory("ConnectionInfo")]
+        [Description("Pass a valid proxy port.")]
+        [Owner("Kenneth_aa")]
+        public void Test_ConnectionInfo_ProxyPort_Valid()
+        {
+            new ConnectionInfo(Resources.HOST, 22, Resources.USERNAME, ProxyTypes.None, Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD, null);
+        }
+
+        [TestMethod]
+        [TestCategory("ConnectionInfo")]
+        [Description("Pass null as host.")]
+        [Owner("Kenneth_aa")]
+        [ExpectedException(typeof(ArgumentException))]
+        public void Test_ConnectionInfo_Host_Null()
+        {
+            new ConnectionInfo(null, 22, Resources.USERNAME, ProxyTypes.None, Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD, null);
+        }
+
+        [TestMethod]
+        [TestCategory("ConnectionInfo")]
+        [Description("Pass String.Empty as host.")]
+        [Owner("Kenneth_aa")]
+        [ExpectedException(typeof(ArgumentException))]
+        public void Test_ConnectionInfo_Host_Empty()
+        {
+            new ConnectionInfo(string.Empty, 22, Resources.USERNAME, ProxyTypes.None, Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD, null);
+        }
+
+        [TestMethod]
+        [TestCategory("ConnectionInfo")]
+        [Description("Pass a valid host.")]
+        [Owner("Kenneth_aa")]
+        public void Test_ConnectionInfo_Host_Valid()
+        {
+            new ConnectionInfo(Resources.HOST, 22, Resources.USERNAME, ProxyTypes.None, Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD, null);
+        }
+
+        [TestMethod]
+        [TestCategory("ConnectionInfo")]
+        [Description("Pass too large port.")]
+        [Owner("Kenneth_aa")]
+        [ExpectedException(typeof(ArgumentOutOfRangeException))]
+        public void Test_ConnectionInfo_Port_Large()
+        {
+            new ConnectionInfo(Resources.HOST, int.MaxValue, Resources.USERNAME, ProxyTypes.None, Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD, null);
+        }
+
+        [TestMethod]
+        [TestCategory("ConnectionInfo")]
+        [Description("Pass too small port.")]
+        [Owner("Kenneth_aa")]
+        [ExpectedException(typeof(ArgumentOutOfRangeException))]
+        public void Test_ConnectionInfo_Port_Small()
+        {
+            new ConnectionInfo(Resources.HOST, int.MinValue, Resources.USERNAME, ProxyTypes.None, Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD, null);
+        }
+
+        [TestMethod]
+        [TestCategory("ConnectionInfo")]
+        [Description("Pass a valid port.")]
+        [Owner("Kenneth_aa")]
+        public void Test_ConnectionInfo_Port_Valid()
+        {
+            new ConnectionInfo(Resources.HOST, 22, Resources.USERNAME, ProxyTypes.None, Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD, null);
+        }
+
+        [TestMethod]
+        [TestCategory("ConnectionInfo")]
+        [Description("Pass null as session.")]
+        [Owner("Kenneth_aa")]
+        [ExpectedException(typeof(ArgumentNullException))]
+        public void Test_ConnectionInfo_Authenticate_Null()
+        {
+            var ret = new ConnectionInfo(Resources.HOST, 22, Resources.USERNAME, ProxyTypes.None, Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD, null);
+            ret.Authenticate(null);
+        }
 	}
 }

+ 5 - 0
Renci.SshClient/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj

@@ -37,11 +37,15 @@
     </StartupObject>
   </PropertyGroup>
   <ItemGroup>
+    <Reference Include="Microsoft.CSharp" />
     <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
     <Reference Include="System" />
     <Reference Include="System.Core">
       <RequiredTargetFramework>3.5</RequiredTargetFramework>
     </Reference>
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+    <Reference Include="System.Xml.Linq" />
   </ItemGroup>
   <ItemGroup>
     <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
@@ -49,6 +53,7 @@
     </CodeAnalysisDependentAssemblyPaths>
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="AuthenticationMethodDerivativesTest.cs" />
     <Compile Include="Common\PipeStreamTest.cs" />
     <Compile Include="ConnectionTest.cs" />
     <Compile Include="Properties\Resources.Designer.cs">

+ 18 - 0
Renci.SshClient/Renci.SshNet.Tests/Security/TestCipher.cs

@@ -14,6 +14,8 @@ namespace Renci.SshNet.Tests.Security
     public class TestCipher
     {
         [TestMethod]
+        [Owner("olegkap")]
+        [TestCategory("Cipher")]
         public void Test_Cipher_TripleDESCBC_Connection()
         {
             var connectionInfo = new PasswordConnectionInfo(Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD);
@@ -28,6 +30,8 @@ namespace Renci.SshNet.Tests.Security
         }
 
         [TestMethod]
+        [Owner("olegkap")]
+        [TestCategory("Cipher")]
         public void Test_Cipher_AEes128CBC_Connection()
         {
             var connectionInfo = new PasswordConnectionInfo(Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD);
@@ -42,6 +46,8 @@ namespace Renci.SshNet.Tests.Security
         }
 
         [TestMethod]
+        [Owner("olegkap")]
+        [TestCategory("Cipher")]
         public void Test_Cipher_Aes192CBC_Connection()
         {
             var connectionInfo = new PasswordConnectionInfo(Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD);
@@ -56,6 +62,8 @@ namespace Renci.SshNet.Tests.Security
         }
 
         [TestMethod]
+        [Owner("olegkap")]
+        [TestCategory("Cipher")]
         public void Test_Cipher_Aes256CBC_Connection()
         {
             var connectionInfo = new PasswordConnectionInfo(Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD);
@@ -70,6 +78,8 @@ namespace Renci.SshNet.Tests.Security
         }
 
         [TestMethod]
+        [Owner("olegkap")]
+        [TestCategory("Cipher")]
         public void Test_Cipher_Aes128CTR_Connection()
         {
             var connectionInfo = new PasswordConnectionInfo(Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD);
@@ -84,6 +94,8 @@ namespace Renci.SshNet.Tests.Security
         }
 
         [TestMethod]
+        [Owner("olegkap")]
+        [TestCategory("Cipher")]
         public void Test_Cipher_Aes192CTR_Connection()
         {
             var connectionInfo = new PasswordConnectionInfo(Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD);
@@ -98,6 +110,8 @@ namespace Renci.SshNet.Tests.Security
         }
 
         [TestMethod]
+        [Owner("olegkap")]
+        [TestCategory("Cipher")]
         public void Test_Cipher_Aes256CTR_Connection()
         {
             var connectionInfo = new PasswordConnectionInfo(Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD);
@@ -112,6 +126,8 @@ namespace Renci.SshNet.Tests.Security
         }
 
         [TestMethod]
+        [Owner("olegkap")]
+        [TestCategory("Cipher")]
         public void Test_Cipher_BlowfishCBC_Connection()
         {
             var connectionInfo = new PasswordConnectionInfo(Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD);
@@ -126,6 +142,8 @@ namespace Renci.SshNet.Tests.Security
         }
 
         [TestMethod]
+        [Owner("olegkap")]
+        [TestCategory("Cipher")]
         public void Test_Cipher_Cast128CBC_Connection()
         {
             var connectionInfo = new PasswordConnectionInfo(Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD);

+ 10 - 0
Renci.SshClient/Renci.SshNet.Tests/Security/TestKeyExchange.cs

@@ -9,6 +9,8 @@ namespace Renci.SshNet.Tests.Security
     {
 
         [TestMethod]
+        [Owner("olegkap")]
+        [TestCategory("Key Exchange")]
         public void Test_KeyExchange_GroupExchange_Sha1_Connection()
         {
             var connectionInfo = new PasswordConnectionInfo(Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD);
@@ -23,6 +25,8 @@ namespace Renci.SshNet.Tests.Security
         }
 
         [TestMethod]
+        [Owner("olegkap")]
+        [TestCategory("Key Exchange")]
         public void Test_KeyExchange_Group14_Sha1_Connection()
         {
             var connectionInfo = new PasswordConnectionInfo(Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD);
@@ -37,6 +41,8 @@ namespace Renci.SshNet.Tests.Security
         }
 
         [TestMethod]
+        [Owner("olegkap")]
+        [TestCategory("Key Exchange")]
         public void Test_KeyExchange_Group1_Sha1_Connection()
         {
             var connectionInfo = new PasswordConnectionInfo(Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD);
@@ -51,6 +57,8 @@ namespace Renci.SshNet.Tests.Security
         }
 
         [TestMethod]
+        [Owner("olegkap")]
+        [TestCategory("Key Exchange")]
         public void Test_KeyExchange_GroupExchange_Sha256_Connection()
         {
             var connectionInfo = new PasswordConnectionInfo(Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD);
@@ -65,6 +73,8 @@ namespace Renci.SshNet.Tests.Security
         }
 
         [TestMethod]
+        [Owner("olegkap")]
+        [TestCategory("Key Exchange")]
         public void Test_KeyExchange_Rekeying()
         {
             var connectionInfo = new PasswordConnectionInfo(Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD);

+ 19 - 5
Renci.SshClient/Renci.SshNet.Tests/Security/TestPrivateKeyFile.cs

@@ -27,6 +27,8 @@ namespace Renci.SshNet.Tests.Security
 		}
 
 		[TestMethod]
+        [Owner("olegkap")]
+        [TestCategory("PrivateKey")]
 		public void Test_PrivateKey_RSA()
 		{
 			var key = @"-----BEGIN RSA PRIVATE KEY-----
@@ -59,7 +61,9 @@ Q4K/6SzJfIzSl/oYoB8xT0LY58qtBEurTZE81mmmiHV/gw6w+fQW
 			new PrivateKeyFile(new MemoryStream(Encoding.ASCII.GetBytes(key)));
 		}
 
-		[TestMethod]
+        [TestMethod]
+        [Owner("olegkap")]
+        [TestCategory("PrivateKey")]
 		public void Test_PrivateKey_RSA_DES_CBC()
 		{
 			var key = @"-----BEGIN RSA PRIVATE KEY-----
@@ -95,7 +99,9 @@ uhSoNyRY0/VZgE+fJ7P0Y5hzgnBDncVH5j57G0q4KTiTBDfuHBTLw+h5Htd5VBGS
 			new PrivateKeyFile(new MemoryStream(Encoding.ASCII.GetBytes(key)), "12345");
 		}
 
-		[TestMethod]
+        [TestMethod]
+        [Owner("olegkap")]
+        [TestCategory("PrivateKey")]
 		public void Test_PrivateKey_RSA_DES_EDE3_CBC()
 		{
 			var key = @"-----BEGIN RSA PRIVATE KEY-----
@@ -131,7 +137,9 @@ bIk+F6YypdWnYjwQMr0e/RBZDVvsFH0XgHESq8hLEFXa6kWzQPIaVw==
 			new PrivateKeyFile(new MemoryStream(Encoding.ASCII.GetBytes(key)), "12345");
 		}
 
-		//[TestMethod]
+        //[TestMethod]
+        //[Owner("olegkap")]
+        //[TestCategory("PrivateKey")]
 		public void Test_PrivateKey_RSA_AES_128_CBC()
 		{
 			var key = @"-----BEGIN RSA PRIVATE KEY-----
@@ -168,6 +176,8 @@ TGwZ2mF2ZKxS3eXVHOKysreLIQQOeMi+rlHAMAfzu5PTQhaYhhFZ2oPBmPsYYrJD
 		}
 
 		//[TestMethod]
+        //[Owner("olegkap")]
+        //[TestCategory("PrivateKey")]
 		public void Test_PrivateKey_RSA_AES_192_CBC()
 		{
 			var key = @"-----BEGIN RSA PRIVATE KEY-----
@@ -203,7 +213,9 @@ BcBcYCqd1X+JFQxp7fID+EGxlMfTjdZM4c51y67EHzMquZSiLEGBQgE8KiJclsIN
 			new PrivateKeyFile(new MemoryStream(Encoding.ASCII.GetBytes(key)), "12345");
 		}
 
-		//[TestMethod]
+        //[TestMethod]
+        //[Owner("olegkap")]
+        //[TestCategory("PrivateKey")]
 		public void Test_PrivateKey_RSA_AES_256_CBC()
 		{
 			var key = @"-----BEGIN RSA PRIVATE KEY-----
@@ -239,7 +251,9 @@ XPIab5czlgSLYA/U9nEg2XU21hKD2kRH1OF0WSlpNhN2SJFViVqlC3v36MgHoWNh
 			new PrivateKeyFile(new MemoryStream(Encoding.ASCII.GetBytes(key)), "12345");
 		}
 
-		//[TestMethod]
+        //[TestMethod]
+        //[Owner("olegkap")]
+        //[TestCategory("PrivateKey")]
 		public void Test_PrivateKey_RSA_DES_EDE3_CFB()
 		{
 			var key = @"-----BEGIN RSA PRIVATE KEY-----

+ 1 - 0
Renci.SshClient/Renci.SshNet.Tests/SshClientTests/TestPortForwarding.cs

@@ -18,6 +18,7 @@ namespace Renci.SshNet.Tests.SshClientTests
 		[TestMethod]
 		[WorkItem(713)]
 		[Owner("kenneth_aa")]
+        [TestCategory("PortForwarding")]
 		[Description("Test if calling Stop on ForwardedPortLocal instance causes wait.")]
 		public void Test_PortForwarding_Local_Stop_Hangs_On_Wait()
 		{

+ 1 - 0
Renci.SshClient/Renci.SshNet/AuthenticationMethod.cs

@@ -35,6 +35,7 @@ namespace Renci.SshNet
         /// Initializes a new instance of the <see cref="AuthenticationMethod"/> class.
         /// </summary>
         /// <param name="username">The username.</param>
+        /// <exception cref="ArgumentException"><paramref name="username"/> is whitespace or null.</exception>
         protected AuthenticationMethod(string username)
         {
             if (username.IsNullOrWhiteSpace())

+ 4 - 1
Renci.SshClient/Renci.SshNet/ConnectionInfo.cs

@@ -208,6 +208,8 @@ namespace Renci.SshNet
         {
         }
 
+        //  TODO: DOCS Add exception documentation for this class.
+
         /// <summary>
         /// Initializes a new instance of the <see cref="ConnectionInfo"/> class.
         /// </summary>
@@ -230,7 +232,7 @@ namespace Renci.SshNet
             if (!host.IsValidHost())
                 throw new ArgumentException("host");
 
-            if (!string.IsNullOrEmpty(proxyHost) && !proxyHost.IsValidHost())
+            if (string.IsNullOrEmpty(proxyHost) && !proxyHost.IsValidHost())
                 throw new ArgumentException("proxyHost");
 
             if (!port.IsValidPort())
@@ -347,6 +349,7 @@ namespace Renci.SshNet
         /// <param name="session">The session to be authenticated.</param>
         /// <returns>true if authenticated; otherwise false.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="session"/> is null.</exception>
+        /// <exception cref="SshAuthenticationException">No suitable authentication method found to complete authentication.</exception>
         public bool Authenticate(Session session)
         {
             var authenticated = AuthenticationResult.Failure;

+ 14 - 0
Renci.SshClient/Renci.SshNet/ExpectAction.cs

@@ -26,8 +26,15 @@ namespace Renci.SshNet
         /// </summary>
         /// <param name="expect">The expect regular expression.</param>
         /// <param name="action">The action to perform.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="expect"/> or <paramref name="action"/> is null.</exception>
         public ExpectAction(Regex expect, Action<string> action)
         {
+            if (expect == null)
+                throw new ArgumentNullException("expect");
+
+            if (action == null)
+                throw new ArgumentNullException("action");
+
             this.Expect = expect;
             this.Action = action;
         }
@@ -37,8 +44,15 @@ namespace Renci.SshNet
         /// </summary>
         /// <param name="expect">The expect expression.</param>
         /// <param name="action">The action to perform.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="expect"/> or <paramref name="action"/> is null.</exception>
         public ExpectAction(string expect, Action<string> action)
         {
+            if (expect == null)
+                throw new ArgumentNullException("expect");
+
+            if (action == null)
+                throw new ArgumentNullException("action");
+
             this.Expect = new Regex(Regex.Escape(expect));
             this.Action = action;
         }

+ 1 - 0
Renci.SshClient/Renci.SshNet/KeyboardInteractiveAuthenticationMethod.NET40.cs

@@ -12,6 +12,7 @@ namespace Renci.SshNet
 {
     public partial  class KeyboardInteractiveAuthenticationMethod : AuthenticationMethod
     {
+        /// <exception cref="ArgumentNullException"><paramref name="action"/> is null.</exception>
         partial void ExecuteThread(Action action)
         {
             Task.Factory.StartNew(action);

+ 1 - 0
Renci.SshClient/Renci.SshNet/KeyboardInteractiveAuthenticationMethod.cs

@@ -43,6 +43,7 @@ namespace Renci.SshNet
         /// <param name="host">The host.</param>
         /// <param name="port">The port.</param>
         /// <param name="username">The username.</param>
+        /// <exception cref="ArgumentException"><paramref name="username"/> is whitespace or null.</exception>
         public KeyboardInteractiveAuthenticationMethod(string username)
             : base(username)
         {

+ 2 - 0
Renci.SshClient/Renci.SshNet/KeyboardInteractiveConnectionInfo.cs

@@ -16,6 +16,8 @@ namespace Renci.SshNet
         /// </summary>
         public event EventHandler<AuthenticationPromptEventArgs> AuthenticationPrompt;
 
+        //  TODO: DOCS Add exception documentation for this class.
+
         /// <summary>
         /// Initializes a new instance of the <see cref="KeyboardInteractiveConnectionInfo"/> class.
         /// </summary>

+ 5 - 1
Renci.SshClient/Renci.SshNet/MessageEventArgs.cs

@@ -14,11 +14,15 @@ namespace Renci.SshNet
         public T Message { get; private set; }
 
         /// <summary>
-        /// Initializes a new instance of the <see cref="MessageEventArgs&lt;T&gt;"/> class.
+        /// Initializes a new instance of the <see cref="MessageEventArgs"/> class.
         /// </summary>
         /// <param name="message">The message.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="message"/> is null.</exception>
         public MessageEventArgs(T message)
         {
+            if (message == null)
+                throw new ArgumentNullException("message");
+
             this.Message = message;
         }
     }

+ 4 - 0
Renci.SshClient/Renci.SshNet/Messages/Connection/ChannelRequest/ExecRequestInfo.cs

@@ -40,9 +40,13 @@ namespace Renci.SshNet.Messages.Connection
         /// Initializes a new instance of the <see cref="ExecRequestInfo"/> class.
         /// </summary>
         /// <param name="command">The command.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="command"/> is null.</exception>
         public ExecRequestInfo(string command)
             : this()
         {
+            if (command == null)
+                throw new System.ArgumentNullException("command");
+
             this.Command = command;
         }
 

+ 5 - 0
Renci.SshClient/Renci.SshNet/NetConfClient.cs

@@ -13,6 +13,7 @@ using System.Diagnostics.CodeAnalysis;
 
 namespace Renci.SshNet
 {
+    //  TODO:   Please help with documentation here, as I don't know the details, specially for the methods not documented.
     /// <summary>
     /// 
     /// </summary>
@@ -110,6 +111,7 @@ namespace Renci.SshNet
         /// <summary>
         /// Gets NetConf server capabilities.
         /// </summary>
+        /// <exception cref="SshConnectionException">Client is not connected.</exception>
         public XmlDocument ServerCapabilities 
         {
             get
@@ -122,6 +124,7 @@ namespace Renci.SshNet
         /// <summary>
         /// Gets NetConf client capabilities.
         /// </summary>
+        /// <exception cref="SshConnectionException">Client is not connected.</exception>
         public XmlDocument ClientCapabilities
         {
             get
@@ -133,6 +136,8 @@ namespace Renci.SshNet
 
         public bool AutomaticMessageIdHandling { get; set; }
 
+        
+        /// <exception cref="SshConnectionException">Client is not connected.</exception>
         public XmlDocument SendReceiveRpc(XmlDocument rpc)
         {
             this.EnsureConnection();

+ 5 - 0
Renci.SshClient/Renci.SshNet/NoneAuthenticationMethod.cs

@@ -31,6 +31,7 @@ namespace Renci.SshNet
         /// <param name="host">The host.</param>
         /// <param name="port">The port.</param>
         /// <param name="username">The username.</param>
+        /// <exception cref="ArgumentException"><paramref name="username"/> is whitespace or null.</exception>
         public NoneAuthenticationMethod(string username)
             : base(username)
         {
@@ -42,8 +43,12 @@ namespace Renci.SshNet
         /// </summary>
         /// <param name="session">The session.</param>
         /// <returns></returns>
+        /// <exception cref="ArgumentNullException"><paramref name="session"/> is null.</exception>
         public override AuthenticationResult Authenticate(Session session)
         {
+            if (session == null)
+                throw new ArgumentNullException("session");
+
             session.UserAuthenticationSuccessReceived += Session_UserAuthenticationSuccessReceived;
             session.UserAuthenticationFailureReceived += Session_UserAuthenticationFailureReceived;
 

+ 1 - 0
Renci.SshClient/Renci.SshNet/PasswordAuthenticationMethod.NET40.cs

@@ -12,6 +12,7 @@ namespace Renci.SshNet
 {
     public partial class PasswordAuthenticationMethod : AuthenticationMethod
     {
+        /// <exception cref="ArgumentNullException"><paramref name="action"/> is null.</exception>
         partial void ExecuteThread(Action action)
         {
             Task.Factory.StartNew(action);

+ 2 - 0
Renci.SshClient/Renci.SshNet/PasswordAuthenticationMethod.cs

@@ -46,6 +46,8 @@ namespace Renci.SshNet
         /// <param name="port">The port.</param>
         /// <param name="username">The username.</param>
         /// <param name="password">The password.</param>
+        /// <exception cref="ArgumentException"><paramref name="username"/> is whitespace or null.</exception>
+        /// <exception cref="ArgumentException"><paramref name="password"/> is null.</exception>
         public PasswordAuthenticationMethod(string username, string password)
             : base(username)
         {

+ 2 - 0
Renci.SshClient/Renci.SshNet/PrivateKeyAuthenticationMethod.cs

@@ -41,9 +41,11 @@ namespace Renci.SshNet
         /// <param name="port">The port.</param>
         /// <param name="username">The username.</param>
         /// <param name="keyFiles">The key files.</param>
+        /// <exception cref="ArgumentException"><paramref name="username"/> is whitespace or null.</exception>
         public PrivateKeyAuthenticationMethod(string username, params PrivateKeyFile[] keyFiles)
             : base(username)
         {
+            //  TODO:   Should throw on keyFiles == null here?
             this.KeyFiles = new Collection<PrivateKeyFile>(keyFiles);
         }
 

+ 36 - 0
Renci.SshClient/Renci.SshNet/ScpClient.NET.cs

@@ -22,8 +22,17 @@ namespace Renci.SshNet
         /// </summary>
         /// <param name="fileInfo">Local file to upload.</param>
         /// <param name="filename">Remote host file name.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="fileInfo"/> or <paramref name="filename"/> is null.</exception>
         public void Upload(FileInfo fileInfo, string filename)
         {
+            if (fileInfo == null)
+                throw new ArgumentNullException("fileInfo");
+
+            if (filename == null)
+                throw new ArgumentNullException("filename"); //  TODO:   Should add IsNullOrWhitespace for this filename parameter?
+
+            //  UNDONE:   EnsureConnection?
+
             using (var input = new PipeStream())
             using (var channel = this.Session.CreateChannel<ChannelSession>())
             {
@@ -50,8 +59,17 @@ namespace Renci.SshNet
         /// </summary>
         /// <param name="directoryInfo">Local directory to upload.</param>
         /// <param name="filename">Remote host directory name.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="ArgumentNullException"/> or <paramref name="filename"/> is null.</exception>
         public void Upload(DirectoryInfo directoryInfo, string filename)
         {
+            if (directoryInfo == null)
+                throw new ArgumentNullException("directoryInfo");
+
+            if (filename == null)
+                throw new ArgumentNullException("filename"); //  TODO:   Should add IsNullOrWhitespace for this filename parameter?
+
+            //  UNDONE:   EnsureConnection?
+
             using (var input = new PipeStream())
             using (var channel = this.Session.CreateChannel<ChannelSession>())
             {
@@ -78,8 +96,17 @@ namespace Renci.SshNet
         /// </summary>
         /// <param name="filename">Remote host file name.</param>
         /// <param name="fileInfo">Local file information.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="fileInfo"/> or <paramref name="filename"/> is null.</exception>
         public void Download(string filename, FileInfo fileInfo)
         {
+            if (fileInfo == null)
+                throw new ArgumentNullException("fileInfo");
+
+            if (filename == null)
+                throw new ArgumentNullException("filename"); //  TODO:   Should add IsNullOrWhitespace for this filename parameter?
+
+            //  UNDONE:   EnsureConnection?
+
             using (var input = new PipeStream())
             using (var channel = this.Session.CreateChannel<ChannelSession>())
             {
@@ -106,8 +133,17 @@ namespace Renci.SshNet
         /// </summary>
         /// <param name="directoryName">Remote host directory name.</param>
         /// <param name="directoryInfo">Local directory information.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="directoryInfo"/> or <paramref name="directoryName"/> is null.</exception>
         public void Download(string directoryName, DirectoryInfo directoryInfo)
         {
+            if (directoryInfo == null)
+                throw new ArgumentNullException("directoryInfo");
+
+            if (directoryName == null)
+                throw new ArgumentNullException("directoryName"); //  TODO:   Should add IsNullOrWhitespace for this filename parameter?
+
+            //  UNDONE:   EnsureConnection?
+
             using (var input = new PipeStream())
             using (var channel = this.Session.CreateChannel<ChannelSession>())
             {

+ 2 - 0
Renci.SshClient/Renci.SshNet/ScpClient.cs

@@ -181,6 +181,8 @@ namespace Renci.SshNet
             if (destination == null)
                 throw new ArgumentNullException("destination");
 
+            //  UNDONE:   Should call EnsureConnection here to keep it consistent? If you add the call, please add to comment: <exception cref="SshConnectionException">Client is not connected.</exception>
+
             using (var input = new PipeStream())
             using (var channel = this.Session.CreateChannel<ChannelSession>())
             {

+ 1 - 0
Renci.SshClient/Renci.SshNet/Session.cs

@@ -412,6 +412,7 @@ namespace Renci.SshNet
         /// </summary>
         public void Connect()
         {
+            //   TODO: Add exception documentation for Proxy.
             if (this.ConnectionInfo == null)
             {
                 throw new ArgumentNullException("connectionInfo");

+ 3 - 0
Renci.SshClient/Renci.SshNet/Sftp/SftpFile.cs

@@ -472,8 +472,11 @@ namespace Renci.SshNet.Sftp
         /// Moves a specified file to a new location on remote machine, providing the option to specify a new file name.
         /// </summary>
         /// <param name="destFileName">The path to move the file to, which can specify a different file name.</param>
+        /// <exception cref="ArgumentNullException"><paramref name="destFileName"/> is null.</exception>
         public void MoveTo(string destFileName)
         {
+            if (destFileName == null)
+                throw new ArgumentNullException("destFileName");
             this._sftpSession.RequestRename(this.FullName, destFileName);
 
             var fullPath = this._sftpSession.GetCanonicalPath(destFileName);

+ 5 - 0
Renci.SshClient/Renci.SshNet/SftpClient.NET40.cs

@@ -8,6 +8,11 @@ namespace Renci.SshNet
     /// </summary>
     public partial class SftpClient
     {
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="action"></param>
+        /// <exception cref="ArgumentNullException"><paramref name="action"/> is null.</exception>
         partial void ExecuteThread(Action action)
         {
             Task.Factory.StartNew(action);

+ 14 - 0
Renci.SshClient/Renci.SshNet/SftpClient.cs

@@ -351,6 +351,7 @@ namespace Renci.SshNet
         /// </summary>
         /// <param name="path">The path.</param>
         /// <returns></returns>
+        /// <exception cref="SshConnectionException">Client is not connected.</exception>
         /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
         public SftpFile Get(string path)
         {
@@ -763,6 +764,7 @@ namespace Renci.SshNet
         /// </summary>
         /// <param name="path">The name of the file or directory to be deleted. Wildcard characters are not supported.</param>
         /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
+        /// <exception cref="SshConnectionException">Client is not connected.</exception>
         public void Delete(string path)
         {
             var file = this.Get(path);
@@ -776,6 +778,7 @@ namespace Renci.SshNet
         /// <param name="path">The file or directory for which to obtain access date and time information.</param>
         /// <returns>A <see cref="System.DateTime"/> structure set to the date and time that the specified file or directory was last accessed. This value is expressed in local time.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
+        /// <exception cref="SshConnectionException">Client is not connected.</exception>
         public DateTime GetLastAccessTime(string path)
         {
             var file = this.Get(path);
@@ -789,6 +792,7 @@ namespace Renci.SshNet
         /// <param name="path">The file or directory for which to obtain access date and time information.</param>
         /// <returns>A <see cref="System.DateTime"/> structure set to the date and time that the specified file or directory was last accessed. This value is expressed in UTC time.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
+        /// <exception cref="SshConnectionException">Client is not connected.</exception>
         public DateTime GetLastAccessTimeUtc(string path)
         {
             var file = this.Get(path);
@@ -802,6 +806,7 @@ namespace Renci.SshNet
         /// <param name="path">The file or directory for which to obtain write date and time information.</param>
         /// <returns>A <see cref="System.DateTime"/> structure set to the date and time that the specified file or directory was last written to. This value is expressed in local time.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
+        /// <exception cref="SshConnectionException">Client is not connected.</exception>
         public DateTime GetLastWriteTime(string path)
         {
             var file = this.Get(path);
@@ -815,6 +820,7 @@ namespace Renci.SshNet
         /// <param name="path">The file or directory for which to obtain write date and time information.</param>
         /// <returns>A <see cref="System.DateTime"/> structure set to the date and time that the specified file or directory was last written to. This value is expressed in UTC time.</returns>
         /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
+        /// <exception cref="SshConnectionException">Client is not connected.</exception>
         public DateTime GetLastWriteTimeUtc(string path)
         {
             var file = this.Get(path);
@@ -1159,6 +1165,8 @@ namespace Renci.SshNet
 
         #endregion
 
+        /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
+        /// <exception cref="SshConnectionException">Client not connected.</exception>
         private IEnumerable<SftpFile> InternalListDirectory(string path, SftpListDirectoryAsyncResult asynchResult)
         {
             if (path == null)
@@ -1198,6 +1206,9 @@ namespace Renci.SshNet
             return result;
         }
 
+        /// <exception cref="ArgumentNullException"><paramref name="path"/> is null or contains whitespace.</exception>
+        /// <exception cref="ArgumentException"><paramref name="output"/> is null.</exception>
+        /// <exception cref="SshConnectionException">Client not connected.</exception>
         private void InternalDownloadFile(string path, Stream output, SftpDownloadAsyncResult asynchResult)
         {
             if (output == null)
@@ -1238,6 +1249,9 @@ namespace Renci.SshNet
             this._sftpSession.RequestClose(handle);
         }
 
+        /// <exception cref="ArgumentNullException"><paramref name="input"/> is null.</exception>
+        /// <exception cref="ArgumentException"><paramref name="path"/> is null or contains whitespace.</exception>
+        /// <exception cref="SshConnectionException">Client not connected.</exception>
         private void InternalUploadFile(Stream input, string path, SftpUploadAsyncResult asynchResult, Flags flags)
         {
             if (input == null)

+ 1 - 0
Renci.SshClient/Renci.SshNet/Shell.NET40.cs

@@ -8,6 +8,7 @@ namespace Renci.SshNet
     /// </summary>
     public partial class Shell 
     {
+        /// <exception cref="ArgumentNullException"><paramref name=" action"/> is null.</exception>
         partial void ExecuteThread(Action action)
         {
             Task.Factory.StartNew(action);

+ 4 - 4
Renci.SshClient/Renci.SshNet/ShellStream.cs

@@ -335,7 +335,7 @@ namespace Renci.SshNet
         /// <summary>
         /// Reads the line from the shell. If line is not available it will block the execution and will wait for new line.
         /// </summary>
-        /// <returns></returns>
+        /// <returns>The line read from the shell.</returns>
         public string ReadLine()
         {
             var text = string.Empty;
@@ -370,7 +370,7 @@ namespace Renci.SshNet
         /// <summary>
         /// Reads text available in the shell.
         /// </summary>
-        /// <returns></returns>
+        /// <returns>The text available in the shell.</returns>
         public string Read()
         {
             var text = string.Empty;
@@ -388,7 +388,7 @@ namespace Renci.SshNet
         /// <summary>
         /// Writes the specified text to the shell.
         /// </summary>
-        /// <param name="text">The text.</param>
+        /// <param name="text">The text to be written to the shell.</param>
         public void Write(string text)
         {
             var data = this._encoding.GetBytes(text);
@@ -398,7 +398,7 @@ namespace Renci.SshNet
         /// <summary>
         /// Writes the line to the shell.
         /// </summary>
-        /// <param name="line">The line.</param>
+        /// <param name="line">The line to be written to the shell.</param>
         public void WriteLine(string line)
         {
             var commandText = string.Format("{0}{1}", line, "\r\n");

+ 14 - 0
Renci.SshClient/Renci.SshNet/SshClient.cs

@@ -18,6 +18,9 @@ namespace Renci.SshNet
         /// </summary>
         private List<ForwardedPort> _forwardedPorts = new List<ForwardedPort>();
 
+        /// <summary>
+        /// If true, causes the connectionInfo object to be disposed.
+        /// </summary>
         private bool _disposeConnectionInfo;
 
         private Stream _inputStream;
@@ -124,8 +127,14 @@ namespace Renci.SshNet
         /// Adds the forwarded port.
         /// </summary>
         /// <param name="port">The port.</param>
+        /// <exception cref="InvalidOperationException">Forwarded port is already added to a different client.</exception>
+        /// <exception cref="ArgumentNullException"><paramref name="port"/> is null.</exception>
+        /// <exception cref="SshConnectionException">Client is not connected.</exception>
         public void AddForwardedPort(ForwardedPort port)
         {
+            if (port == null)
+                throw new ArgumentNullException("port");
+
             //  Ensure that connection is established.
             this.EnsureConnection();
 
@@ -160,6 +169,7 @@ namespace Renci.SshNet
         /// </summary>
         /// <param name="commandText">The command text.</param>
         /// <returns><see cref="SshCommand"/> object.</returns>
+        /// <exception cref="SshConnectionException">Client is not connected.</exception>
         public SshCommand CreateCommand(string commandText)
         {
             return this.CreateCommand(commandText, Encoding.UTF8);
@@ -171,6 +181,8 @@ namespace Renci.SshNet
         /// <param name="commandText">The command text.</param>
         /// <param name="encoding">The encoding to use for results.</param>
         /// <returns><see cref="SshCommand"/> object which uses specified encoding.</returns>
+        /// <exception cref="SshConnectionException">Client is not connected.</exception>
+        /// <exception cref="ArgumentNullException"><paramref name="commandText"/> or <paramref name="encoding"/> is null.</exception>
         public SshCommand CreateCommand(string commandText, Encoding encoding)
         {
             //  Ensure that connection is established.
@@ -188,6 +200,8 @@ namespace Renci.SshNet
         /// <exception cref="ArgumentException">CommandText property is empty.</exception>
         /// <exception cref="Renci.SshNet.Common.SshException">Invalid Operation - An existing channel was used to execute this command.</exception>
         /// <exception cref="InvalidOperationException">Asynchronous operation is already in progress.</exception>
+        /// <exception cref="SshConnectionException">Client is not connected.</exception>
+        /// <exception cref="ArgumentNullException"><paramref name="commandText"/> is null.</exception>
         public SshCommand RunCommand(string commandText)
         {
             var cmd = this.CreateCommand(commandText);

+ 1 - 0
Renci.SshClient/Renci.SshNet/SshCommand.NET40.cs

@@ -8,6 +8,7 @@ namespace Renci.SshNet
     /// </summary>
     public partial class SshCommand 
     {
+        /// <exception cref="ArgumentNullException"><paramref name=" action"/> is null.</exception>
         partial void ExecuteThread(Action action)
         {
             Task.Factory.StartNew(action);

+ 4 - 0
Renci.SshClient/Renci.SshNet/SshCommand.cs

@@ -124,11 +124,15 @@ namespace Renci.SshNet
         /// <param name="session">The session.</param>
         /// <param name="commandText">The command text.</param>
         /// <param name="encoding">The encoding.</param>
+        /// <exception cref="ArgumentNullException">Either <paramref name="session"/>, <paramref name="commandText"/> or <paramref name="encoding"/> is null.</exception>
         internal SshCommand(Session session, string commandText, Encoding encoding)
         {
             if (session == null)
                 throw new ArgumentNullException("session");
 
+            if (commandText == null)
+                throw new ArgumentNullException("commandText");
+
             this._encoding = encoding;
             this._session = session;
             this.CommandText = commandText;

+ 1 - 0
Renci.SshClient/Renci.SshNet/SubsystemSession.cs

@@ -46,6 +46,7 @@ namespace Renci.SshNet.Sftp
         {
             get
             {
+                //  UNDONE:   _channel.RemoteChannelNumber may be called before _channel is set.
                 return this._channel.RemoteChannelNumber;
             }
         }