summaryrefslogtreecommitdiff
path: root/cli/tests/DenoWinRunner.cs
diff options
context:
space:
mode:
authorMaayan Hanin <maayan.asa.hanin@gmail.com>2020-07-09 22:06:51 +0300
committerGitHub <noreply@github.com>2020-07-09 21:06:51 +0200
commitedb7a0eead3604316b3cca2ac9122c5599445a63 (patch)
treee8d7fe06992decf52c81678b4c000a6edeb922fd /cli/tests/DenoWinRunner.cs
parent202e7fa6ad366ee56a6d070e94eaecb6dbc745bf (diff)
fix(cli): panic when stdio is null on windows (#6528)
Fixes: #6409
Diffstat (limited to 'cli/tests/DenoWinRunner.cs')
-rw-r--r--cli/tests/DenoWinRunner.cs127
1 files changed, 127 insertions, 0 deletions
diff --git a/cli/tests/DenoWinRunner.cs b/cli/tests/DenoWinRunner.cs
new file mode 100644
index 000000000..7879d146d
--- /dev/null
+++ b/cli/tests/DenoWinRunner.cs
@@ -0,0 +1,127 @@
+using System;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Threading.Tasks;
+
+[Flags]
+public enum DenoConstraints : int
+{
+ None = 0,
+ NoStdin = 1,
+ NoStdout = 2,
+ NoStderr = 4
+}
+
+public class DenoWinRunner
+{
+ private const int STD_INPUT_HANDLE = -10;
+ private const int STD_OUTPUT_HANDLE = -11;
+ private const int STD_ERROR_HANDLE = -12;
+
+ private const int FILE_NOT_FOUND = 2;
+ private const int WAIT_TIMEOUT = 258;
+
+ [DllImport("kernel32.dll")]
+ private static extern void SetStdHandle(int nStdHandle, IntPtr handle);
+
+ /// <summary>
+ /// Runs Deno.exe under the specified constraints
+ /// </summary>
+ /// <param name="pathToDenoExe">Path to the Deno.exe file. Can be absolute or relative</param>
+ /// <param name="pathToTestScript">Path to the script file Deno should run.</param>
+ /// <param name="constraints">The contrainsts to apply to the Deno process</param>
+ /// <param name="timeoutMilliseconds">How long to wait for the Deno process to exit</param>
+ /// <returns>The deno.exe exit code, or an exit code provided by the test runner</returns>
+ public static int RunDenoScript(string pathToDenoExe, string pathToTestScript, DenoConstraints constraints, uint timeoutMilliseconds = 1000)
+ {
+ try
+ {
+ if (!File.Exists(pathToDenoExe))
+ {
+ Console.Error.WriteLine("Cannot find Deno.exe at " + pathToDenoExe);
+ return FILE_NOT_FOUND;
+ }
+
+ if (!File.Exists(pathToTestScript))
+ {
+ Console.Error.WriteLine("Cannot find test script at " + pathToTestScript);
+ return FILE_NOT_FOUND;
+ }
+
+ ProcessStartInfo startInfo = new ProcessStartInfo(pathToDenoExe)
+ {
+ ErrorDialog = false,
+ UseShellExecute = false,
+ Arguments = @"run -A " + pathToTestScript,
+ RedirectStandardInput = !constraints.HasFlag(DenoConstraints.NoStdin),
+ RedirectStandardOutput = !constraints.HasFlag(DenoConstraints.NoStdout),
+ RedirectStandardError = !constraints.HasFlag(DenoConstraints.NoStderr)
+ };
+
+ startInfo.Environment.Add("RUST_BACKTRACE", "1");
+
+ if (constraints.HasFlag(DenoConstraints.NoStdin))
+ {
+ SetStdHandle(STD_INPUT_HANDLE, (IntPtr)null);
+ }
+
+ if (constraints.HasFlag(DenoConstraints.NoStdout))
+ {
+ SetStdHandle(STD_OUTPUT_HANDLE, (IntPtr)null);
+ }
+
+ if (constraints.HasFlag(DenoConstraints.NoStderr))
+ {
+ SetStdHandle(STD_ERROR_HANDLE, (IntPtr)null);
+ }
+
+ Process process = new Process { StartInfo = startInfo };
+ process.Start();
+
+ Task<string> stdErrTask = startInfo.RedirectStandardError ?
+ process.StandardError.ReadToEndAsync() : Task.FromResult<string>(null);
+ Task<string> stdOutTask = startInfo.RedirectStandardOutput ?
+ process.StandardOutput.ReadToEndAsync() : Task.FromResult<string>(null);
+
+ if (!process.WaitForExit((int)timeoutMilliseconds))
+ {
+ Console.Error.WriteLine("Timed out waiting for Deno process to exit");
+ try
+ {
+ process.Kill();
+ }
+ catch
+ {
+ // Kill might fail, either because the process already exited or due to some other error
+ Console.Error.WriteLine("Failure killing the Deno process - possible Zombie Deno.exe process");
+ }
+ return WAIT_TIMEOUT;
+ }
+
+ // If the Deno process wrote to STDERR - append it to our STDERR
+ if (!constraints.HasFlag(DenoConstraints.NoStderr))
+ {
+ string error = stdErrTask.Result;
+ if (!string.IsNullOrWhiteSpace(error))
+ {
+ Console.Error.WriteLine(error);
+ }
+ }
+
+ return process.ExitCode;
+
+ }
+ catch (Win32Exception ex)
+ {
+ Console.Error.WriteLine("Win32Exception: code = " + ex.ErrorCode + ", message: " + ex.Message);
+ return ex.NativeErrorCode;
+ }
+ catch (Exception ex)
+ {
+ Console.Error.WriteLine("Exception: message: " + ex.Message);
+ return -1;
+ }
+ }
+} \ No newline at end of file