SshCommandTest.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. using System.Diagnostics;
  2. #if !NET
  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. [Timeout(15000)]
  161. public async Task Test_ExecuteAsync_Disconnect()
  162. {
  163. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  164. {
  165. client.Connect();
  166. using var cmd = client.CreateCommand("sleep 10s");
  167. cmd.CommandTimeout = TimeSpan.FromSeconds(2);
  168. Task executeTask = cmd.ExecuteAsync();
  169. client.Disconnect();
  170. // Waiting for timeout is not optimal here, but better than hanging indefinitely.
  171. await Assert.ThrowsExceptionAsync<SshOperationTimeoutException>(() => executeTask);
  172. }
  173. }
  174. [TestMethod]
  175. public void Test_Execute_InvalidCommand()
  176. {
  177. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  178. {
  179. client.Connect();
  180. using var cmd = client.CreateCommand(";");
  181. cmd.Execute();
  182. if (string.IsNullOrEmpty(cmd.Error))
  183. {
  184. Assert.Fail("Operation should fail");
  185. }
  186. Assert.IsTrue(cmd.ExitStatus > 0);
  187. client.Disconnect();
  188. }
  189. }
  190. [TestMethod]
  191. public void Test_Execute_InvalidCommand_Then_Execute_ValidCommand()
  192. {
  193. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  194. {
  195. client.Connect();
  196. using var cmd = client.CreateCommand(";");
  197. cmd.Execute();
  198. if (string.IsNullOrEmpty(cmd.Error))
  199. {
  200. Assert.Fail("Operation should fail");
  201. }
  202. Assert.IsTrue(cmd.ExitStatus > 0);
  203. var result = ExecuteTestCommand(client);
  204. client.Disconnect();
  205. Assert.IsTrue(result);
  206. }
  207. }
  208. [TestMethod]
  209. public void Test_Execute_Command_Reconnect_Execute_Command()
  210. {
  211. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  212. {
  213. client.Connect();
  214. var result = ExecuteTestCommand(client);
  215. Assert.IsTrue(result);
  216. client.Disconnect();
  217. client.Connect();
  218. result = ExecuteTestCommand(client);
  219. Assert.IsTrue(result);
  220. client.Disconnect();
  221. }
  222. }
  223. [TestMethod]
  224. public void Test_Execute_Command_ExitStatus()
  225. {
  226. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  227. {
  228. client.Connect();
  229. using var cmd = client.RunCommand("exit 128");
  230. Assert.AreEqual(128, cmd.ExitStatus);
  231. Assert.IsNull(cmd.ExitSignal);
  232. }
  233. }
  234. [TestMethod]
  235. public void Test_Execute_Command_Asynchronously()
  236. {
  237. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  238. {
  239. client.Connect();
  240. using var callbackCalled = new ManualResetEventSlim();
  241. using var cmd = client.CreateCommand("sleep 2s; echo 'test'");
  242. var asyncResult = cmd.BeginExecute(new AsyncCallback((s) =>
  243. {
  244. callbackCalled.Set();
  245. }), state: null);
  246. while (!asyncResult.IsCompleted)
  247. {
  248. Thread.Sleep(100);
  249. }
  250. Assert.IsTrue(asyncResult.AsyncWaitHandle.WaitOne(0));
  251. cmd.EndExecute(asyncResult);
  252. Assert.AreEqual("test\n", cmd.Result);
  253. Assert.IsTrue(callbackCalled.Wait(TimeSpan.FromSeconds(1)));
  254. client.Disconnect();
  255. }
  256. }
  257. [TestMethod]
  258. public void Test_Execute_Command_Asynchronously_With_Error()
  259. {
  260. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  261. {
  262. client.Connect();
  263. using var cmd = client.CreateCommand("sleep 2s; ;");
  264. var asyncResult = cmd.BeginExecute(null, null);
  265. Assert.IsTrue(asyncResult.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(5)));
  266. cmd.EndExecute(asyncResult);
  267. Assert.IsFalse(string.IsNullOrEmpty(cmd.Error));
  268. client.Disconnect();
  269. }
  270. }
  271. [TestMethod]
  272. public void Test_Execute_Command_Asynchronously_With_Callback_On_Different_Thread()
  273. {
  274. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  275. {
  276. client.Connect();
  277. var currentThreadId = Thread.CurrentThread.ManagedThreadId;
  278. int callbackThreadId = 0;
  279. using var callbackCalled = new ManualResetEventSlim();
  280. using var cmd = client.CreateCommand("sleep 2s; echo 'test'");
  281. var asyncResult = cmd.BeginExecute(new AsyncCallback((s) =>
  282. {
  283. callbackThreadId = Thread.CurrentThread.ManagedThreadId;
  284. callbackCalled.Set();
  285. }), null);
  286. cmd.EndExecute(asyncResult);
  287. Assert.IsTrue(callbackCalled.Wait(TimeSpan.FromSeconds(1)));
  288. Assert.AreNotEqual(currentThreadId, callbackThreadId);
  289. client.Disconnect();
  290. }
  291. }
  292. /// <summary>
  293. /// Tests for Issue 563.
  294. /// </summary>
  295. [WorkItem(563), TestMethod]
  296. public void Test_Execute_Command_Same_Object_Different_Commands()
  297. {
  298. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  299. {
  300. client.Connect();
  301. using var cmd = client.CreateCommand("echo 12345");
  302. cmd.Execute();
  303. Assert.AreEqual("12345\n", cmd.Result);
  304. cmd.Execute("echo 23456");
  305. Assert.AreEqual("23456\n", cmd.Result);
  306. client.Disconnect();
  307. }
  308. }
  309. [TestMethod]
  310. public void Test_Get_Result_Without_Execution()
  311. {
  312. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  313. {
  314. client.Connect();
  315. using var cmd = client.CreateCommand("ls -l");
  316. Assert.AreEqual(string.Empty, cmd.Result);
  317. Assert.AreEqual(string.Empty, cmd.Error);
  318. client.Disconnect();
  319. }
  320. }
  321. [WorkItem(703), TestMethod]
  322. public void Test_EndExecute_Before_BeginExecute()
  323. {
  324. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  325. {
  326. client.Connect();
  327. using var cmd = client.CreateCommand("ls -l");
  328. Assert.ThrowsException<ArgumentNullException>(() => cmd.EndExecute(null));
  329. client.Disconnect();
  330. }
  331. }
  332. /// <summary>
  333. ///A test for BeginExecute
  334. ///</summary>
  335. [TestMethod()]
  336. public void BeginExecuteTest()
  337. {
  338. string expected = "123\n";
  339. string result;
  340. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  341. {
  342. #region Example SshCommand CreateCommand BeginExecute IsCompleted EndExecute
  343. client.Connect();
  344. using var cmd = client.CreateCommand("sleep 2s;echo 123"); // Perform long running task
  345. var asynch = cmd.BeginExecute();
  346. Assert.IsTrue(asynch.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(5)));
  347. result = cmd.EndExecute(asynch);
  348. client.Disconnect();
  349. #endregion
  350. Assert.IsNotNull(asynch);
  351. Assert.AreEqual(expected, result);
  352. }
  353. }
  354. [TestMethod]
  355. public void Test_MultipleThread_100_MultipleConnections()
  356. {
  357. try
  358. {
  359. var options = new ParallelOptions()
  360. {
  361. MaxDegreeOfParallelism = 8
  362. };
  363. Parallel.For(0, 100, options,
  364. () =>
  365. {
  366. var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password);
  367. client.Connect();
  368. return client;
  369. },
  370. (int counter, ParallelLoopState pls, SshClient client) =>
  371. {
  372. var result = ExecuteTestCommand(client);
  373. Debug.WriteLine(string.Format("TestMultipleThreadMultipleConnections #{0}", counter));
  374. Assert.IsTrue(result);
  375. return client;
  376. },
  377. (SshClient client) =>
  378. {
  379. client.Disconnect();
  380. client.Dispose();
  381. }
  382. );
  383. }
  384. catch (Exception exp)
  385. {
  386. Assert.Fail(exp.ToString());
  387. }
  388. }
  389. [TestMethod]
  390. public void Test_MultipleThread_100_MultipleSessions()
  391. {
  392. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  393. {
  394. client.Connect();
  395. Parallel.For(0, 100,
  396. (counter) =>
  397. {
  398. var result = ExecuteTestCommand(client);
  399. Debug.WriteLine(string.Format("TestMultipleThreadMultipleConnections #{0}", counter));
  400. Assert.IsTrue(result);
  401. }
  402. );
  403. client.Disconnect();
  404. }
  405. }
  406. [TestMethod]
  407. public void Test_ExecuteAsync_Dispose_CommandFinishes()
  408. {
  409. using (var client = new SshClient(SshServerHostName, SshServerPort, User.UserName, User.Password))
  410. {
  411. client.Connect();
  412. var cmd = client.CreateCommand("sleep 5s");
  413. var asyncResult = cmd.BeginExecute(null, null);
  414. cmd.Dispose();
  415. Assert.IsTrue(asyncResult.AsyncWaitHandle.WaitOne(0));
  416. Assert.ThrowsException<ObjectDisposedException>(() => cmd.EndExecute(asyncResult));
  417. }
  418. }
  419. private static bool ExecuteTestCommand(SshClient s)
  420. {
  421. var testValue = Guid.NewGuid().ToString();
  422. var command = string.Format("echo -n {0}", testValue);
  423. using var cmd = s.CreateCommand(command);
  424. var result = cmd.Execute();
  425. return result.Equals(testValue);
  426. }
  427. }
  428. }