diff --git a/Community.Wsa.Sdk.Tests/AdbClientTests.cs b/Community.Wsa.Sdk.Tests/AdbClientTests.cs index a707442..d71bfed 100644 --- a/Community.Wsa.Sdk.Tests/AdbClientTests.cs +++ b/Community.Wsa.Sdk.Tests/AdbClientTests.cs @@ -643,4 +643,19 @@ await AssertExecutedWith( "1" ); } + + [Test] + public async Task ExecuteCommandAsync_ShouldExecute() + { + var actualOutput = await AssertExecutedWith( + "foobar", + (adb) => adb.ExecuteCommandAsync("test", new string[] { "a", "b" }), + "shell", + "test", + "a", + "b" + ); + + actualOutput.Should().BeEquivalentTo("foobar"); + } } diff --git a/Community.Wsa.Sdk.Tests/ProcessTestHelpers.cs b/Community.Wsa.Sdk.Tests/ProcessTestHelpers.cs index 233a8cc..0542a0d 100644 --- a/Community.Wsa.Sdk.Tests/ProcessTestHelpers.cs +++ b/Community.Wsa.Sdk.Tests/ProcessTestHelpers.cs @@ -11,7 +11,12 @@ namespace Community.Wsa.Sdk.Tests; internal static class ProcessTestHelpers { - public static IProcess Exits(string output = "", int executionTime = 10, int exitCode = 0) + public static IProcess Exits( + string output = "", + string errorOutput = "", + int executionTime = 10, + int exitCode = 0 + ) { var p = A.Fake(); @@ -19,8 +24,13 @@ public static IProcess Exits(string output = "", int executionTime = 10, int exi new MemoryStream(Encoding.UTF8.GetBytes(output)), Encoding.UTF8 ); + var stdErr = new StreamReader( + new MemoryStream(Encoding.UTF8.GetBytes(errorOutput)), + Encoding.UTF8 + ); A.CallTo(() => p.StandardOutput).Returns(stdOut); + A.CallTo(() => p.StandardError).Returns(stdErr); A.CallTo(() => p.WaitForExitAsync()) .Returns(Task.Delay(executionTime).ContinueWith((_) => exitCode)); A.CallTo(() => p.WaitForExitAsync(A._)) @@ -35,7 +45,9 @@ public static IProcess TimesOut() var p = A.Fake(); var stdOut = new StreamReader(Stream.Null, Encoding.UTF8); + var stdErr = new StreamReader(Stream.Null, Encoding.UTF8); + A.CallTo(() => p.StandardError).Returns(stdErr); A.CallTo(() => p.StandardOutput).Returns(stdOut); A.CallTo(() => p.WaitForExitAsync(A._)) .Returns(Task.Delay(10).ContinueWith((_) => null)); diff --git a/Community.Wsa.Sdk/AdbClient.cs b/Community.Wsa.Sdk/AdbClient.cs index e205c04..ef828e8 100644 --- a/Community.Wsa.Sdk/AdbClient.cs +++ b/Community.Wsa.Sdk/AdbClient.cs @@ -148,12 +148,13 @@ public Task DisconnectAsync(EndPoint endPoint) } /// - public Task ExecuteCommandAsync(string command, string[] arguments) + public Task ExecuteCommandAsync(string command, params string[] arguments) { - var adbArguments = new string[arguments.Length + 1]; - Array.Copy(arguments, 0, adbArguments, 1, arguments.Length); + var adbArguments = new string[arguments.Length + 2]; + Array.Copy(arguments, 0, adbArguments, 2, arguments.Length); adbArguments[0] = "shell"; + adbArguments[1] = command; return ExecuteAdbCommandAsync(adbArguments); } @@ -320,6 +321,7 @@ internal virtual async Task ExecuteAdbCommandAsync( var startInfo = new ProcessStartInfo(PathToAdb!) { RedirectStandardOutput = true, + RedirectStandardError = true, CreateNoWindow = true }; var strCommand = $"adb {string.Join(" ", arguments)}"; @@ -333,31 +335,53 @@ internal virtual async Task ExecuteAdbCommandAsync( _processManager.Start(startInfo) ?? throw new AdbException(AdbError.CannotStartAdb); var stdOutTask = process.StandardOutput.ReadToEndAsync().ConfigureAwait(false); + var stdErrTask = process.StandardError.ReadToEndAsync().ConfigureAwait(false); var exitCode = await process.WaitForExitAsync(10_000).ConfigureAwait(false); string stdOut; + string stdErr; if (!exitCode.HasValue) { process.Kill(); stdOut = await stdOutTask; - throw new AdbException(AdbError.CommandTimedOut, strCommand, stdOut); + stdErr = await stdErrTask; + throw new AdbException(AdbError.CommandTimedOut, strCommand, stdOut + "\n" + stdErr); } stdOut = await stdOutTask; + stdErr = await stdErrTask; + var completeOutput = stdOut + "\n" + stdErr; if (exitCode != 0) { - throw new AdbException(AdbError.CommandFailed, strCommand, stdOut); + throw new AdbException(AdbError.CommandFailed, strCommand, completeOutput); } + ValidateOutput(outputMustInclude, outputMustNotInclude, stdOut, strCommand, completeOutput); + + return stdOut; + } + + private static void ValidateOutput( + string? outputMustInclude, + string? outputMustNotInclude, + string stdOut, + string strCommand, + string completeOutput + ) + { if ( !string.IsNullOrEmpty(outputMustInclude) && !stdOut.Contains(outputMustInclude, StringComparison.OrdinalIgnoreCase) ) { - throw new AdbException(AdbError.CommandFinishedWithInvalidOutput, strCommand, stdOut); + throw new AdbException( + AdbError.CommandFinishedWithInvalidOutput, + strCommand, + completeOutput + ); } if ( @@ -365,9 +389,11 @@ internal virtual async Task ExecuteAdbCommandAsync( && stdOut.Contains(outputMustNotInclude, StringComparison.OrdinalIgnoreCase) ) { - throw new AdbException(AdbError.CommandFinishedWithInvalidOutput, strCommand, stdOut); + throw new AdbException( + AdbError.CommandFinishedWithInvalidOutput, + strCommand, + completeOutput + ); } - - return stdOut; } }