SshCommandTest.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. using System.Diagnostics;
  2. #if !NET8_0_OR_GREATER
  3. using Renci.SshNet.Abstractions;
  4. #endif
  5. using Renci.SshNet.Common;
  6. namespace Renci.SshNet.IntegrationTests.OldIntegrationTests
  7. {
  8. /// <summary>
  9. /// Represents SSH command that can be executed.
  10. /// </summary>
  11. [TestClass]
  12. public class SshCommandTest : IntegrationTestBase
  13. {
  14. [TestMethod]
  15. public void Test_Run_SingleCommand()
  16. {
  17. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  18. {
  19. #region Example SshCommand RunCommand Result
  20. client.Connect();
  21. var testValue = Guid.NewGuid().ToString();
  22. using var command = client.RunCommand(string.Format("echo {0}", testValue));
  23. var result = command.Result;
  24. result = result.Substring(0, result.Length - 1); // Remove \n character returned by command
  25. client.Disconnect();
  26. #endregion
  27. Assert.AreEqual(testValue, result);
  28. }
  29. }
  30. [TestMethod]
  31. public void Test_Execute_SingleCommand()
  32. {
  33. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  34. {
  35. #region Example SshCommand CreateCommand Execute
  36. client.Connect();
  37. var testValue = Guid.NewGuid().ToString();
  38. var command = string.Format("echo -n {0}", testValue);
  39. using var cmd = client.CreateCommand(command);
  40. var result = cmd.Execute();
  41. client.Disconnect();
  42. #endregion
  43. Assert.AreEqual(testValue, result);
  44. }
  45. }
  46. [TestMethod]
  47. [Timeout(5000)]
  48. public void Test_CancelAsync_Unfinished_Command()
  49. {
  50. using var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password);
  51. client.Connect();
  52. var testValue = Guid.NewGuid().ToString();
  53. using var cmd = client.CreateCommand($"sleep 15s; echo {testValue}");
  54. var asyncResult = cmd.BeginExecute();
  55. cmd.CancelAsync();
  56. var tce = Assert.ThrowsException<TaskCanceledException>(() => cmd.EndExecute(asyncResult));
  57. Assert.AreEqual(CancellationToken.None, tce.CancellationToken);
  58. Assert.IsTrue(asyncResult.IsCompleted);
  59. Assert.IsTrue(asyncResult.AsyncWaitHandle.WaitOne(0));
  60. Assert.AreEqual(string.Empty, cmd.Result);
  61. Assert.AreEqual("TERM", cmd.ExitSignal);
  62. Assert.IsNull(cmd.ExitStatus);
  63. }
  64. [TestMethod]
  65. [Timeout(5000)]
  66. public async Task Test_CancelAsync_Kill_Unfinished_Command()
  67. {
  68. using var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password);
  69. client.Connect();
  70. var testValue = Guid.NewGuid().ToString();
  71. using var cmd = client.CreateCommand($"sleep 15s; echo {testValue}");
  72. var asyncResult = cmd.BeginExecute();
  73. Task<string> executeTask = Task.Factory.FromAsync(asyncResult, cmd.EndExecute);
  74. cmd.CancelAsync(forceKill: true);
  75. var tce = await Assert.ThrowsExceptionAsync<TaskCanceledException>(() => executeTask);
  76. Assert.AreEqual(CancellationToken.None, tce.CancellationToken);
  77. Assert.IsTrue(asyncResult.IsCompleted);
  78. Assert.IsTrue(asyncResult.AsyncWaitHandle.WaitOne(0));
  79. Assert.AreEqual(string.Empty, cmd.Result);
  80. Assert.AreEqual("KILL", cmd.ExitSignal);
  81. Assert.IsNull(cmd.ExitStatus);
  82. }
  83. [TestMethod]
  84. public void Test_CancelAsync_Finished_Command()
  85. {
  86. using var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password);
  87. client.Connect();
  88. var testValue = Guid.NewGuid().ToString();
  89. using var cmd = client.CreateCommand($"echo -n {testValue}");
  90. var asyncResult = cmd.BeginExecute();
  91. Assert.IsTrue(asyncResult.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(5)));
  92. cmd.CancelAsync(); // Should not throw
  93. Assert.AreEqual(testValue, cmd.EndExecute(asyncResult)); // Should not throw
  94. cmd.CancelAsync(); // Should not throw
  95. Assert.IsTrue(asyncResult.IsCompleted);
  96. Assert.AreEqual(testValue, cmd.Result);
  97. Assert.AreEqual(0, cmd.ExitStatus);
  98. Assert.IsNull(cmd.ExitSignal);
  99. }
  100. [TestMethod]
  101. [Timeout(5000)]
  102. public async Task Test_ExecuteAsync_CancellationToken()
  103. {
  104. using var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password);
  105. client.Connect();
  106. var testValue = Guid.NewGuid().ToString();
  107. using var cmd = client.CreateCommand($"sleep 15s; echo {testValue}");
  108. using CancellationTokenSource cts = new();
  109. Task executeTask = cmd.ExecuteAsync(cts.Token);
  110. await cts.CancelAsync();
  111. var tce = await Assert.ThrowsExceptionAsync<TaskCanceledException>(() => executeTask);
  112. Assert.AreSame(executeTask, tce.Task);
  113. Assert.AreEqual(cts.Token, tce.CancellationToken);
  114. Assert.AreEqual(string.Empty, cmd.Result);
  115. Assert.AreEqual("TERM", cmd.ExitSignal);
  116. Assert.IsNull(cmd.ExitStatus);
  117. }
  118. [TestMethod]
  119. public void Test_Execute_ExtendedOutputStream()
  120. {
  121. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  122. {
  123. #region Example SshCommand CreateCommand Execute ExtendedOutputStream
  124. client.Connect();
  125. using var cmd = client.CreateCommand("echo 12345; echo 654321 >&2");
  126. using var reader = new StreamReader(cmd.ExtendedOutputStream);
  127. Assert.AreEqual("12345\n", cmd.Execute());
  128. Assert.AreEqual("654321\n", reader.ReadToEnd());
  129. client.Disconnect();
  130. #endregion
  131. }
  132. }
  133. [TestMethod]
  134. public void Test_Execute_Timeout()
  135. {
  136. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  137. {
  138. client.Connect();
  139. using var cmd = client.CreateCommand("sleep 10s");
  140. cmd.CommandTimeout = TimeSpan.FromSeconds(2);
  141. Assert.ThrowsException<SshOperationTimeoutException>(cmd.Execute);
  142. client.Disconnect();
  143. }
  144. }
  145. [TestMethod]
  146. public async Task Test_ExecuteAsync_Timeout()
  147. {
  148. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  149. {
  150. client.Connect();
  151. using var cmd = client.CreateCommand("sleep 10s");
  152. cmd.CommandTimeout = TimeSpan.FromSeconds(2);
  153. Task executeTask = cmd.ExecuteAsync();
  154. Assert.IsTrue(((IAsyncResult)executeTask).AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(3)));
  155. await Assert.ThrowsExceptionAsync<SshOperationTimeoutException>(() => executeTask);
  156. client.Disconnect();
  157. }
  158. }
  159. [TestMethod]
  160. public void Test_Execute_InvalidCommand()
  161. {
  162. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  163. {
  164. client.Connect();
  165. using var cmd = client.CreateCommand(";");
  166. cmd.Execute();
  167. if (string.IsNullOrEmpty(cmd.Error))
  168. {
  169. Assert.Fail("Operation should fail");
  170. }
  171. Assert.IsTrue(cmd.ExitStatus > 0);
  172. client.Disconnect();
  173. }
  174. }
  175. [TestMethod]
  176. public void Test_Execute_InvalidCommand_Then_Execute_ValidCommand()
  177. {
  178. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  179. {
  180. client.Connect();
  181. using var cmd = client.CreateCommand(";");
  182. cmd.Execute();
  183. if (string.IsNullOrEmpty(cmd.Error))
  184. {
  185. Assert.Fail("Operation should fail");
  186. }
  187. Assert.IsTrue(cmd.ExitStatus > 0);
  188. var result = ExecuteTestCommand(client);
  189. client.Disconnect();
  190. Assert.IsTrue(result);
  191. }
  192. }
  193. [TestMethod]
  194. public void Test_Execute_Command_Reconnect_Execute_Command()
  195. {
  196. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  197. {
  198. client.Connect();
  199. var result = ExecuteTestCommand(client);
  200. Assert.IsTrue(result);
  201. client.Disconnect();
  202. client.Connect();
  203. result = ExecuteTestCommand(client);
  204. Assert.IsTrue(result);
  205. client.Disconnect();
  206. }
  207. }
  208. [TestMethod]
  209. public void Test_Execute_Command_ExitStatus()
  210. {
  211. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  212. {
  213. client.Connect();
  214. using var cmd = client.RunCommand("exit 128");
  215. Assert.AreEqual(128, cmd.ExitStatus);
  216. Assert.IsNull(cmd.ExitSignal);
  217. }
  218. }
  219. [TestMethod]
  220. public void Test_Execute_Command_Asynchronously()
  221. {
  222. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  223. {
  224. client.Connect();
  225. using var callbackCalled = new ManualResetEventSlim();
  226. using var cmd = client.CreateCommand("sleep 2s; echo 'test'");
  227. var asyncResult = cmd.BeginExecute(new AsyncCallback((s) =>
  228. {
  229. callbackCalled.Set();
  230. }), state: null);
  231. while (!asyncResult.IsCompleted)
  232. {
  233. Thread.Sleep(100);
  234. }
  235. Assert.IsTrue(asyncResult.AsyncWaitHandle.WaitOne(0));
  236. cmd.EndExecute(asyncResult);
  237. Assert.AreEqual("test\n", cmd.Result);
  238. Assert.IsTrue(callbackCalled.Wait(TimeSpan.FromSeconds(1)));
  239. client.Disconnect();
  240. }
  241. }
  242. [TestMethod]
  243. public void Test_Execute_Command_Asynchronously_With_Error()
  244. {
  245. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  246. {
  247. client.Connect();
  248. using var cmd = client.CreateCommand("sleep 2s; ;");
  249. var asyncResult = cmd.BeginExecute(null, null);
  250. Assert.IsTrue(asyncResult.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(5)));
  251. cmd.EndExecute(asyncResult);
  252. Assert.IsFalse(string.IsNullOrEmpty(cmd.Error));
  253. client.Disconnect();
  254. }
  255. }
  256. [TestMethod]
  257. public void Test_Execute_Command_Asynchronously_With_Callback_On_Different_Thread()
  258. {
  259. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  260. {
  261. client.Connect();
  262. var currentThreadId = Thread.CurrentThread.ManagedThreadId;
  263. int callbackThreadId = 0;
  264. using var callbackCalled = new ManualResetEventSlim();
  265. using var cmd = client.CreateCommand("sleep 2s; echo 'test'");
  266. var asyncResult = cmd.BeginExecute(new AsyncCallback((s) =>
  267. {
  268. callbackThreadId = Thread.CurrentThread.ManagedThreadId;
  269. callbackCalled.Set();
  270. }), null);
  271. cmd.EndExecute(asyncResult);
  272. Assert.IsTrue(callbackCalled.Wait(TimeSpan.FromSeconds(1)));
  273. Assert.AreNotEqual(currentThreadId, callbackThreadId);
  274. client.Disconnect();
  275. }
  276. }
  277. /// <summary>
  278. /// Tests for Issue 563.
  279. /// </summary>
  280. [WorkItem(563), TestMethod]
  281. public void Test_Execute_Command_Same_Object_Different_Commands()
  282. {
  283. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  284. {
  285. client.Connect();
  286. using var cmd = client.CreateCommand("echo 12345");
  287. cmd.Execute();
  288. Assert.AreEqual("12345\n", cmd.Result);
  289. cmd.Execute("echo 23456");
  290. Assert.AreEqual("23456\n", cmd.Result);
  291. client.Disconnect();
  292. }
  293. }
  294. [TestMethod]
  295. public void Test_Get_Result_Without_Execution()
  296. {
  297. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  298. {
  299. client.Connect();
  300. using var cmd = client.CreateCommand("ls -l");
  301. Assert.AreEqual(string.Empty, cmd.Result);
  302. Assert.AreEqual(string.Empty, cmd.Error);
  303. client.Disconnect();
  304. }
  305. }
  306. [WorkItem(703), TestMethod]
  307. public void Test_EndExecute_Before_BeginExecute()
  308. {
  309. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  310. {
  311. client.Connect();
  312. using var cmd = client.CreateCommand("ls -l");
  313. Assert.ThrowsException<ArgumentNullException>(() => cmd.EndExecute(null));
  314. client.Disconnect();
  315. }
  316. }
  317. /// <summary>
  318. ///A test for BeginExecute
  319. ///</summary>
  320. [TestMethod()]
  321. public void BeginExecuteTest()
  322. {
  323. string expected = "123\n";
  324. string result;
  325. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  326. {
  327. #region Example SshCommand CreateCommand BeginExecute IsCompleted EndExecute
  328. client.Connect();
  329. using var cmd = client.CreateCommand("sleep 2s;echo 123"); // Perform long running task
  330. var asynch = cmd.BeginExecute();
  331. Assert.IsTrue(asynch.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(5)));
  332. result = cmd.EndExecute(asynch);
  333. client.Disconnect();
  334. #endregion
  335. Assert.IsNotNull(asynch);
  336. Assert.AreEqual(expected, result);
  337. }
  338. }
  339. [TestMethod]
  340. public void Test_MultipleThread_100_MultipleConnections()
  341. {
  342. try
  343. {
  344. var options = new ParallelOptions()
  345. {
  346. MaxDegreeOfParallelism = 8
  347. };
  348. Parallel.For(0, 100, options,
  349. () =>
  350. {
  351. var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password);
  352. client.Connect();
  353. return client;
  354. },
  355. (int counter, ParallelLoopState pls, SshClient client) =>
  356. {
  357. var result = ExecuteTestCommand(client);
  358. Debug.WriteLine(string.Format("TestMultipleThreadMultipleConnections #{0}", counter));
  359. Assert.IsTrue(result);
  360. return client;
  361. },
  362. (SshClient client) =>
  363. {
  364. client.Disconnect();
  365. client.Dispose();
  366. }
  367. );
  368. }
  369. catch (Exception exp)
  370. {
  371. Assert.Fail(exp.ToString());
  372. }
  373. }
  374. [TestMethod]
  375. public void Test_MultipleThread_100_MultipleSessions()
  376. {
  377. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  378. {
  379. client.Connect();
  380. Parallel.For(0, 100,
  381. (counter) =>
  382. {
  383. var result = ExecuteTestCommand(client);
  384. Debug.WriteLine(string.Format("TestMultipleThreadMultipleConnections #{0}", counter));
  385. Assert.IsTrue(result);
  386. }
  387. );
  388. client.Disconnect();
  389. }
  390. }
  391. [TestMethod]
  392. public void Test_ExecuteAsync_Dispose_CommandFinishes()
  393. {
  394. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  395. {
  396. client.Connect();
  397. var cmd = client.CreateCommand("sleep 5s");
  398. var asyncResult = cmd.BeginExecute(null, null);
  399. cmd.Dispose();
  400. Assert.IsTrue(asyncResult.AsyncWaitHandle.WaitOne(0));
  401. Assert.ThrowsException<ObjectDisposedException>(() => cmd.EndExecute(asyncResult));
  402. }
  403. }
  404. private static bool ExecuteTestCommand(SshClient s)
  405. {
  406. var testValue = Guid.NewGuid().ToString();
  407. var command = string.Format("echo -n {0}", testValue);
  408. using var cmd = s.CreateCommand(command);
  409. var result = cmd.Execute();
  410. return result.Equals(testValue);
  411. }
  412. }
  413. }