SessionTest_Connected.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. using System;
  2. using System.Linq;
  3. using System.Net.Sockets;
  4. using System.Text;
  5. using System.Text.RegularExpressions;
  6. using System.Threading;
  7. using Microsoft.VisualStudio.TestTools.UnitTesting;
  8. using Moq;
  9. using Renci.SshNet.Messages.Connection;
  10. using Renci.SshNet.Messages.Transport;
  11. namespace Renci.SshNet.Tests.Classes
  12. {
  13. [TestClass]
  14. public class SessionTest_Connected : SessionTest_ConnectedBase
  15. {
  16. private IgnoreMessage _ignoreMessage;
  17. protected override void SetupData()
  18. {
  19. base.SetupData();
  20. var data = new byte[10];
  21. Random.NextBytes(data);
  22. _ignoreMessage = new IgnoreMessage(data);
  23. }
  24. protected override void Act()
  25. {
  26. }
  27. [TestMethod]
  28. public void ClientVersionIsRenciSshNet()
  29. {
  30. Assert.IsTrue(Regex.IsMatch(
  31. Session.ClientVersion,
  32. // Ends with e.g. 2024.1.1 plus some optional metadata not containing '-'
  33. @"^SSH-2\.0-Renci\.SshNet\.SshClient\.\d{4}\.\d+\.\d+(_[a-zA-Z0-9_\.]+)?$"));
  34. }
  35. [TestMethod]
  36. public void IncludeStrictKexPseudoAlgorithmInInitKex()
  37. {
  38. Assert.IsTrue(FirstKexReceived.Wait(1000));
  39. Assert.IsTrue(ServerBytesReceivedRegister.Count > 0);
  40. var kexInitMessage = new KeyExchangeInitMessage();
  41. kexInitMessage.Load(ServerBytesReceivedRegister[0], 4 + 1 + 1, ServerBytesReceivedRegister[0].Length - 4 - 1 - 1);
  42. Assert.IsTrue(kexInitMessage.KeyExchangeAlgorithms.Contains("kex-strict-c-v00@openssh.com"));
  43. }
  44. [TestMethod]
  45. public void ShouldNotIncludeStrictKexPseudoAlgorithmInSubsequentKex()
  46. {
  47. Assert.IsTrue(FirstKexReceived.Wait(1000));
  48. using var subsequentKexReceived = new ManualResetEventSlim();
  49. bool kexContainsPseudoAlg = true;
  50. ServerListener.BytesReceived += ServerListener_BytesReceived;
  51. void ServerListener_BytesReceived(byte[] bytesReceived, Socket socket)
  52. {
  53. if (bytesReceived.Length > 5 && bytesReceived[5] == 20)
  54. {
  55. // SSH_MSG_KEXINIT = 20
  56. var kexInitMessage = new KeyExchangeInitMessage();
  57. kexInitMessage.Load(bytesReceived, 6, bytesReceived.Length - 6);
  58. kexContainsPseudoAlg = kexInitMessage.KeyExchangeAlgorithms.Contains("kex-strict-c-v00@openssh.com");
  59. subsequentKexReceived.Set();
  60. }
  61. }
  62. Session.SendMessage(Session.ClientInitMessage);
  63. Assert.IsTrue(subsequentKexReceived.Wait(1000));
  64. Assert.IsFalse(kexContainsPseudoAlg);
  65. ServerListener.BytesReceived -= ServerListener_BytesReceived;
  66. }
  67. [TestMethod]
  68. public void ConnectionInfoShouldReturnConnectionInfoPassedThroughConstructor()
  69. {
  70. Assert.AreSame(ConnectionInfo, Session.ConnectionInfo);
  71. }
  72. [TestMethod]
  73. public void IsConnectedShouldReturnTrue()
  74. {
  75. Assert.IsTrue(Session.IsConnected);
  76. }
  77. [TestMethod]
  78. public void SendMessageShouldSendPacketToServer()
  79. {
  80. Thread.Sleep(100);
  81. ServerBytesReceivedRegister.Clear();
  82. Session.SendMessage(_ignoreMessage);
  83. // give session time to process message
  84. Thread.Sleep(100);
  85. Assert.AreEqual(1, ServerBytesReceivedRegister.Count);
  86. }
  87. [TestMethod]
  88. [DataRow(true)]
  89. [DataRow(false)]
  90. public void UnknownGlobalRequestWithWantReply(bool wantReply)
  91. {
  92. Thread.Sleep(100);
  93. ServerBytesReceivedRegister.Clear();
  94. var globalRequest =
  95. new GlobalRequestMessage(Encoding.ASCII.GetBytes("unknown-request"), wantReply).GetPacket(8, null);
  96. ServerSocket.Send(globalRequest, 4, globalRequest.Length - 4, SocketFlags.None);
  97. Thread.Sleep(100);
  98. if (wantReply)
  99. {
  100. // Should have sent a failure reply.
  101. Assert.AreEqual(1, ServerBytesReceivedRegister.Count);
  102. Assert.AreEqual(82, ServerBytesReceivedRegister[0][5], "Expected to have sent SSH_MSG_REQUEST_FAILURE(82)");
  103. }
  104. else
  105. {
  106. // Should not have sent any reply.
  107. Assert.AreEqual(0, ServerBytesReceivedRegister.Count);
  108. }
  109. Assert.AreEqual(0, ErrorOccurredRegister.Count);
  110. }
  111. [TestMethod]
  112. public void SessionIdShouldReturnExchangeHashCalculatedFromKeyExchangeInitMessage()
  113. {
  114. Assert.IsNotNull(Session.SessionId);
  115. Assert.AreSame(SessionId, Session.SessionId);
  116. }
  117. [TestMethod]
  118. public void ServerVersionShouldNotReturnNull()
  119. {
  120. Assert.IsNotNull(Session.ServerVersion);
  121. Assert.AreEqual("SSH-2.0-OurServerStub", Session.ServerVersion);
  122. }
  123. [TestMethod]
  124. public void WaitOnHandle_WaitHandle_ShouldThrowArgumentNullExceptionWhenWaitHandleIsNull()
  125. {
  126. const WaitHandle waitHandle = null;
  127. try
  128. {
  129. Session.WaitOnHandle(waitHandle);
  130. Assert.Fail();
  131. }
  132. catch (ArgumentNullException ex)
  133. {
  134. Assert.IsNull(ex.InnerException);
  135. Assert.AreEqual("waitHandle", ex.ParamName);
  136. }
  137. }
  138. [TestMethod]
  139. public void WaitOnHandle_WaitHandleAndTimeout_ShouldThrowArgumentNullExceptionWhenWaitHandleIsNull()
  140. {
  141. const WaitHandle waitHandle = null;
  142. var timeout = TimeSpan.FromMinutes(5);
  143. try
  144. {
  145. Session.WaitOnHandle(waitHandle, timeout);
  146. Assert.Fail();
  147. }
  148. catch (ArgumentNullException ex)
  149. {
  150. Assert.IsNull(ex.InnerException);
  151. Assert.AreEqual("waitHandle", ex.ParamName);
  152. }
  153. }
  154. [TestMethod]
  155. public void ISession_ConnectionInfoShouldReturnConnectionInfoPassedThroughConstructor()
  156. {
  157. var session = (ISession)Session;
  158. Assert.AreSame(ConnectionInfo, session.ConnectionInfo);
  159. }
  160. [TestMethod]
  161. public void ISession_MessageListenerCompletedShouldNotBeSignaled()
  162. {
  163. var session = (ISession)Session;
  164. Assert.IsNotNull(session.MessageListenerCompleted);
  165. Assert.IsFalse(session.MessageListenerCompleted.WaitOne(0));
  166. }
  167. [TestMethod]
  168. public void ISession_SendMessageShouldSendPacketToServer()
  169. {
  170. Thread.Sleep(100);
  171. var session = (ISession)Session;
  172. ServerBytesReceivedRegister.Clear();
  173. session.SendMessage(_ignoreMessage);
  174. // give session time to process message
  175. Thread.Sleep(100);
  176. Assert.AreEqual(1, ServerBytesReceivedRegister.Count);
  177. }
  178. [TestMethod]
  179. public void ISession_TrySendMessageShouldSendPacketToServerAndReturnTrue()
  180. {
  181. Thread.Sleep(100);
  182. var session = (ISession)Session;
  183. ServerBytesReceivedRegister.Clear();
  184. var actual = session.TrySendMessage(new IgnoreMessage());
  185. // give session time to process message
  186. Thread.Sleep(100);
  187. Assert.IsTrue(actual);
  188. Assert.AreEqual(1, ServerBytesReceivedRegister.Count);
  189. }
  190. [TestMethod]
  191. public void ISession_WaitOnHandleShouldThrowArgumentNullExceptionWhenWaitHandleIsNull()
  192. {
  193. const WaitHandle waitHandle = null;
  194. var session = (ISession)Session;
  195. try
  196. {
  197. session.WaitOnHandle(waitHandle);
  198. Assert.Fail();
  199. }
  200. catch (ArgumentNullException ex)
  201. {
  202. Assert.IsNull(ex.InnerException);
  203. Assert.AreEqual("waitHandle", ex.ParamName);
  204. }
  205. }
  206. [TestMethod]
  207. public void ISession_TryWait_WaitHandleAndTimeout_ShouldReturnSuccessIfWaitHandleIsSignaled()
  208. {
  209. var session = (ISession)Session;
  210. var waitHandle = new ManualResetEvent(true);
  211. var result = session.TryWait(waitHandle, TimeSpan.FromMilliseconds(0));
  212. Assert.AreEqual(WaitResult.Success, result);
  213. }
  214. [TestMethod]
  215. public void ISession_TryWait_WaitHandleAndTimeout_ShouldReturnTimedOutIfWaitHandleIsNotSignaled()
  216. {
  217. var session = (ISession)Session;
  218. var waitHandle = new ManualResetEvent(false);
  219. var result = session.TryWait(waitHandle, TimeSpan.FromMilliseconds(0));
  220. Assert.AreEqual(WaitResult.TimedOut, result);
  221. }
  222. [TestMethod]
  223. public void ISession_TryWait_WaitHandleAndTimeout_ShouldThrowArgumentNullExceptionWhenWaitHandleIsNull()
  224. {
  225. var session = (ISession)Session;
  226. const WaitHandle waitHandle = null;
  227. try
  228. {
  229. _ = session.TryWait(waitHandle, Timeout.InfiniteTimeSpan);
  230. Assert.Fail();
  231. }
  232. catch (ArgumentNullException ex)
  233. {
  234. Assert.IsNull(ex.InnerException);
  235. Assert.AreEqual("waitHandle", ex.ParamName);
  236. }
  237. }
  238. [TestMethod]
  239. public void ISession_TryWait_WaitHandleAndTimeoutAndException_ShouldReturnSuccessIfWaitHandleIsSignaled()
  240. {
  241. var session = (ISession)Session;
  242. var waitHandle = new ManualResetEvent(true);
  243. var result = session.TryWait(waitHandle, TimeSpan.FromMilliseconds(0), out var exception);
  244. Assert.AreEqual(WaitResult.Success, result);
  245. Assert.IsNull(exception);
  246. }
  247. [TestMethod]
  248. public void ISession_TryWait_WaitHandleAndTimeoutAndException_ShouldReturnTimedOutIfWaitHandleIsNotSignaled()
  249. {
  250. var session = (ISession)Session;
  251. var waitHandle = new ManualResetEvent(false);
  252. var result = session.TryWait(waitHandle, TimeSpan.FromMilliseconds(0), out var exception);
  253. Assert.AreEqual(WaitResult.TimedOut, result);
  254. Assert.IsNull(exception);
  255. }
  256. [TestMethod]
  257. public void ISession_TryWait_WaitHandleAndTimeoutAndException_ShouldThrowArgumentNullExceptionWhenWaitHandleIsNull()
  258. {
  259. var session = (ISession)Session;
  260. const WaitHandle waitHandle = null;
  261. Exception exception = null;
  262. try
  263. {
  264. session.TryWait(waitHandle, Timeout.InfiniteTimeSpan, out exception);
  265. Assert.Fail();
  266. }
  267. catch (ArgumentNullException ex)
  268. {
  269. Assert.IsNull(ex.InnerException);
  270. Assert.AreEqual("waitHandle", ex.ParamName);
  271. Assert.IsNull(exception);
  272. }
  273. }
  274. [TestMethod]
  275. public void ClientSocketShouldBeConnected()
  276. {
  277. Assert.IsNotNull(ClientSocket);
  278. Assert.IsTrue(ClientSocket.Connected);
  279. }
  280. [TestMethod]
  281. public void CreateConnectorOnServiceFactoryShouldHaveBeenInvokedOnce()
  282. {
  283. ServiceFactoryMock.Verify(p => p.CreateConnector(ConnectionInfo, SocketFactoryMock.Object), Times.Once());
  284. }
  285. [TestMethod]
  286. public void ConnectorOnConnectorShouldHaveBeenInvokedOnce()
  287. {
  288. ConnectorMock.Verify(p => p.Connect(ConnectionInfo), Times.Once());
  289. }
  290. }
  291. }