-
-
Notifications
You must be signed in to change notification settings - Fork 952
Feature/executeasync #937
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/executeasync #937
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -56,6 +56,71 @@ public void Test_Run_SingleCommand() | |
} | ||
} | ||
|
||
#if FEATURE_TAP | ||
[TestMethod] | ||
[TestCategory("integration")] | ||
public async Task Test_Run_SingleCommandAsync() | ||
{ | ||
var host = Resources.HOST; | ||
var username = Resources.USERNAME; | ||
var password = Resources.PASSWORD; | ||
|
||
using (var client = new SshClient(host, username, password)) | ||
{ | ||
#region Example SshCommand RunCommand Result Async | ||
var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(60)).Token; | ||
await client.ConnectAsync(cancellationToken); | ||
|
||
var testValue = Guid.NewGuid().ToString(); | ||
var command = await client.RunCommandAsync(string.Format("echo {0}", testValue), cancellationToken); | ||
var result = await new StreamReader(command.OutputStream).ReadToEndAsync(); | ||
kendallb marked this conversation as resolved.
Show resolved
Hide resolved
|
||
result = result.Substring(0, result.Length - 1); // Remove \n character returned by command | ||
|
||
client.Disconnect(); | ||
#endregion | ||
|
||
Assert.IsTrue(result.Equals(testValue)); | ||
} | ||
} | ||
|
||
[TestMethod] | ||
[TestCategory("integration")] | ||
public async Task Test_Run_SingleCommandAsync_WithShortTimeout() | ||
{ | ||
var host = Resources.HOST; | ||
var username = Resources.USERNAME; | ||
var password = Resources.PASSWORD; | ||
|
||
using (var client = new SshClient(host, username, password)) | ||
{ | ||
#region Example SshCommand RunCommand Result Async With Short Timeout | ||
var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(60)).Token; | ||
await client.ConnectAsync(cancellationToken); | ||
|
||
// Timeout in 100ms | ||
var shortTimeout = new CancellationTokenSource(TimeSpan.FromMilliseconds(100)).Token; | ||
|
||
var testValue = Guid.NewGuid().ToString(); | ||
string result; | ||
try | ||
{ | ||
var command = await client.RunCommandAsync(string.Format("echo {0};/bin/sleep 5", testValue), shortTimeout); | ||
result = await new StreamReader(command.OutputStream).ReadToEndAsync(); | ||
result = result.Substring(0, result.Length - 1); // Remove \n character returned by command | ||
} | ||
catch (OperationCanceledException) | ||
{ | ||
result = "canceled"; | ||
} | ||
|
||
client.Disconnect(); | ||
#endregion | ||
|
||
Assert.IsTrue(result.Equals("canceled")); | ||
} | ||
} | ||
#endif | ||
|
||
[TestMethod] | ||
[TestCategory("integration")] | ||
public void Test_Execute_SingleCommand() | ||
|
@@ -266,7 +331,7 @@ public void Test_Execute_Command_ExitStatus() | |
client.Connect(); | ||
|
||
var cmd = client.RunCommand("exit 128"); | ||
|
||
Console.WriteLine(cmd.ExitStatus); | ||
|
||
client.Disconnect(); | ||
|
@@ -500,6 +565,33 @@ public void Test_Execute_Invalid_Command() | |
} | ||
} | ||
|
||
#if FEATURE_TAP | ||
[TestMethod] | ||
[TestCategory("integration")] | ||
public async Task Test_Execute_Invalid_CommandAsync() | ||
{ | ||
using (var client = new SshClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD)) | ||
{ | ||
#region Example SshCommand CreateCommand Error Async | ||
|
||
await client.ConnectAsync(default); | ||
|
||
var cmd = client.CreateCommand(";"); | ||
await cmd.ExecuteAsync(default); | ||
var error = await new StreamReader(cmd.ExtendedOutputStream).ReadToEndAsync(); | ||
if (!string.IsNullOrEmpty(error)) | ||
{ | ||
Console.WriteLine(error); | ||
} | ||
|
||
client.Disconnect(); | ||
|
||
#endregion | ||
|
||
Assert.Inconclusive(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there something to discuss here? Console.WriteLine and Inconclusive... |
||
} | ||
} | ||
#endif | ||
|
||
/// <summary> | ||
///A test for BeginExecute | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> | ||
<s:String x:Key="/Default/Environment/Hierarchy/Build/BuildTool/CustomBuildToolPath/@EntryValue">C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Current\Bin\MSBuild.exe</s:String> | ||
<s:Int64 x:Key="/Default/Environment/Hierarchy/Build/BuildTool/MsbuildVersion/@EntryValue">1048576</s:Int64></wpf:ResourceDictionary> |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,10 @@ | |
using System.Text; | ||
using System.Diagnostics.CodeAnalysis; | ||
using System.Net; | ||
#if FEATURE_TAP | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
#endif | ||
using Renci.SshNet.Common; | ||
|
||
namespace Renci.SshNet | ||
|
@@ -275,6 +279,31 @@ public SshCommand RunCommand(string commandText) | |
return cmd; | ||
} | ||
|
||
#if FEATURE_TAP | ||
/// <summary> | ||
/// Creates and executes the command. | ||
/// </summary> | ||
/// <param name="commandText">The command text.</param> | ||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to observe.</param> | ||
/// <returns>Returns an instance of <see cref="Task{SshCommand}"/> with execution results.</returns> | ||
/// <remarks>This method internally uses asynchronous calls.</remarks> | ||
/// <example> | ||
/// <code source="..\..\src\Renci.SshNet.Tests\Classes\SshCommandTest.cs" region="Example SshCommand RunCommand Result Async" language="C#" title="Running simple command async" /> | ||
/// <code source="..\..\src\Renci.SshNet.Tests\Classes\SshCommandTest.cs" region="Example SshCommand RunCommand Result Async With Short Timeout" language="C#" title="Running simple command with short timeout async" /> | ||
/// </example> | ||
/// <exception cref="ArgumentException">CommandText property is empty.</exception> | ||
/// <exception cref="T: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 <c>null</c>.</exception> | ||
public async Task<SshCommand> RunCommandAsync(string commandText, CancellationToken cancellationToken) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The more I think about it I don't feel we should have such simple helpers... yes, this is aligned with the sync version, but... something to discuss with Gert, I think. |
||
{ | ||
var cmd = CreateCommand(commandText); | ||
await cmd.ExecuteAsync(cancellationToken).ConfigureAwait(false); | ||
return cmd; | ||
} | ||
#endif | ||
|
||
/// <summary> | ||
/// Creates the shell. | ||
/// </summary> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When CancellationTokenSource is used with timeout, it should be disposed, otherwise Timers will pile up. SOmething like: