diff options
Diffstat (limited to 'cli/tests')
-rw-r--r-- | cli/tests/DenoWinRunner.cs | 127 | ||||
-rw-r--r-- | cli/tests/DenoWinRunner.ps1 | 10 | ||||
-rw-r--r-- | cli/tests/integration_tests.rs | 59 |
3 files changed, 196 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 diff --git a/cli/tests/DenoWinRunner.ps1 b/cli/tests/DenoWinRunner.ps1 new file mode 100644 index 000000000..203b5d36c --- /dev/null +++ b/cli/tests/DenoWinRunner.ps1 @@ -0,0 +1,10 @@ +$Source = [IO.File]::ReadAllText("$PSScriptRoot\DenoWinRunner.cs") +$denoExePath = $args[0] +$scriptPath = $args[1] +$constraints = $args[2] +$timeout = 5000; +Add-Type -TypeDefinition $Source -Language CSharp +Write-Output("Running Deno script: " + $args[1]) +$code = [DenoWinRunner]::RunDenoScript($denoExePath, $scriptPath, $constraints, $timeout) +Write-Output("Deno.exe or the test wrapper has exited with code: $code") +exit $code diff --git a/cli/tests/integration_tests.rs b/cli/tests/integration_tests.rs index 87a6f9d63..2ec25d0d0 100644 --- a/cli/tests/integration_tests.rs +++ b/cli/tests/integration_tests.rs @@ -3116,3 +3116,62 @@ fn set_raw_should_not_panic_on_no_tty() { let stderr = std::str::from_utf8(&output.stderr).unwrap().trim(); assert!(stderr.contains("BadResource")); } + +#[cfg(windows)] +enum WinProcConstraints { + NoStdIn, + NoStdOut, + NoStdErr, +} + +#[cfg(windows)] +fn run_deno_script_constrained( + script_path: std::path::PathBuf, + constraints: WinProcConstraints, +) -> Result<(), i64> { + let file_path = "cli/tests/DenoWinRunner.ps1"; + let constraints = match constraints { + WinProcConstraints::NoStdIn => "1", + WinProcConstraints::NoStdOut => "2", + WinProcConstraints::NoStdErr => "4", + }; + let deno_exe_path = util::deno_exe_path() + .into_os_string() + .into_string() + .unwrap(); + + let deno_script_path = script_path.into_os_string().into_string().unwrap(); + + let args = vec![&deno_exe_path[..], &deno_script_path[..], constraints]; + util::run_powershell_script_file(file_path, args) +} + +#[cfg(windows)] +#[test] +fn should_not_panic_on_no_stdin() { + let output = run_deno_script_constrained( + util::tests_path().join("echo.ts"), + WinProcConstraints::NoStdIn, + ); + output.unwrap(); +} + +#[cfg(windows)] +#[test] +fn should_not_panic_on_no_stdout() { + let output = run_deno_script_constrained( + util::tests_path().join("echo.ts"), + WinProcConstraints::NoStdOut, + ); + output.unwrap(); +} + +#[cfg(windows)] +#[test] +fn should_not_panic_on_no_stderr() { + let output = run_deno_script_constrained( + util::tests_path().join("echo.ts"), + WinProcConstraints::NoStdErr, + ); + output.unwrap(); +} |