diff --git a/test/powershell/Host/ConsoleHost.Tests.ps1 b/test/powershell/Host/ConsoleHost.Tests.ps1 index 97a445d36e..94e66c6d92 100644 --- a/test/powershell/Host/ConsoleHost.Tests.ps1 +++ b/test/powershell/Host/ConsoleHost.Tests.ps1 @@ -1,8 +1,40 @@ using namespace System.Diagnostics -Describe "ConsoleHost unit tests" -Tag 'Slow' { +Describe "ConsoleHost unit tests" { - $powershell = Join-Path -Path $PsHome -ChildPath "powershell" + BeforeAll { + $powershell = Join-Path -Path $PsHome -ChildPath "powershell" + + function NewProcessStartInfo([string]$CommandLine, [switch]$RedirectStdIn) + { + return [ProcessStartInfo]@{ + FileName = $powershell + Arguments = $CommandLine + RedirectStandardInput = $RedirectStdIn + RedirectStandardOutput = $true + RedirectStandardError = $true + UseShellExecute = $false + } + } + + function RunPowerShell([ProcessStartInfo]$si) + { + $process = [Process]::Start($si) + + return $process + } + + function EnsureChildHasExited([Process]$process, [int]$WaitTimeInMS = 15000) + { + $process.WaitForExit($WaitTimeInMS) + + if (!$process.HasExited) + { + $process.HasExited | Should Be $true + $process.Kill() + } + } + } Context "CommandLine" { It "simple -args" { @@ -54,49 +86,89 @@ Describe "ConsoleHost unit tests" -Tag 'Slow' { } } - Context "Redirected standard handles" { - function NewProcessStartInfo([string]$CommandLine, [switch]$RedirectStdIn) - { - return [ProcessStartInfo]@{ - FileName = $powershell - Arguments = $CommandLine - RedirectStandardInput = $RedirectStdIn - RedirectStandardOutput = $true - RedirectStandardError = $true - UseShellExecute = $false - } - } - - function RunPowerShell([ProcessStartInfo]$si) - { - $process = [Process]::Start($si) - - return $process - } - - function EnsureChildHasExited([Process]$process, [int]$WaitTimeInMS = 15000) - { - $process.WaitForExit($WaitTimeInMS) - - if (!$process.HasExited) - { - $process.HasExited | Should Be $true - $process.Kill() - } - } - + Context "Redirected standard output" { It "Simple redirected output" { $si = NewProcessStartInfo "-noprofile 1+1" $process = RunPowerShell $si $process.StandardOutput.ReadToEnd() | Should Be 2 EnsureChildHasExited $process } + } + Context "Input redirected but not reading from stdin (not really interactive)" { + # Tests under this context are testing that we do not read from StandardInput + # even though it is redirected - we want to make sure we don't hang. + # So none of these tests should close StandardInput + + It "Redirected input w/ implict -Command w/ -NonInteractive" { + $si = NewProcessStartInfo "-NonInteractive -noprofile 1+1" -RedirectStdIn + $process = RunPowerShell $si + $process.StandardOutput.ReadToEnd() | Should Be 2 + EnsureChildHasExited $process + } + + It "Redirected input w/ implicit -Command w/o -NonInteractive" { + $si = NewProcessStartInfo "-noprofile 1+1" -RedirectStdIn + $process = RunPowerShell $si + $process.StandardOutput.ReadToEnd() | Should Be 2 + EnsureChildHasExited $process + } + + It "Redirected input w/ explict -Command w/ -NonInteractive" { + $si = NewProcessStartInfo "-NonInteractive -noprofile -Command 1+1" -RedirectStdIn + $process = RunPowerShell $si + $process.StandardOutput.ReadToEnd() | Should Be 2 + EnsureChildHasExited $process + } + + It "Redirected input w/ explicit -Command w/o -NonInteractive" { + $si = NewProcessStartInfo "-noprofile -Command 1+1" -RedirectStdIn + $process = RunPowerShell $si + $process.StandardOutput.ReadToEnd() | Should Be 2 + EnsureChildHasExited $process + } + + It "Redirected input w/ -File w/ -NonInteractive" { + '1+1' | Out-File -Encoding Ascii -FilePath TestDrive:test.ps1 -Force + $si = NewProcessStartInfo "-noprofile -NonInteractive -File $testDrive\test.ps1" -RedirectStdIn + $process = RunPowerShell $si + $process.StandardOutput.ReadToEnd() | Should Be 2 + EnsureChildHasExited $process + } + + It "Redirected input w/ -File w/o -NonInteractive" { + '1+1' | Out-File -Encoding Ascii -FilePath TestDrive:test.ps1 -Force + $si = NewProcessStartInfo "-noprofile -File $testDrive\test.ps1" -RedirectStdIn + $process = RunPowerShell $si + $process.StandardOutput.ReadToEnd() | Should Be 2 + EnsureChildHasExited $process + } + } + + Context "Redirected standard input for 'interactive' use" { $nl = [Environment]::Newline - # Redirected input is broken on Windows in .NET Core - It "Redirected input" -Pending:$IsWindows { - $si = NewProcessStartInfo "-noprofile ""`$function:prompt = { 'PS> ' }""" -RedirectStdIn + # All of the following tests replace the prompt (either via an initial command or interactively) + # so that we can read StandardOutput and realiably know exactly what the prompt is. + + It "Interactive redirected input" { + $si = NewProcessStartInfo "-noprofile -nologo" -RedirectStdIn + $process = RunPowerShell $si + $process.StandardInput.Write("`$function:prompt = { 'PS> ' }`n") + $null = $process.StandardOutput.ReadLine() + $process.StandardInput.Write("1+1`n") + $process.StandardOutput.ReadLine() | Should Be "PS> 1+1" + $process.StandardOutput.ReadLine() | Should Be "2" + $process.StandardInput.Write("1+2`n") + $process.StandardOutput.ReadLine() | Should Be "PS> 1+2" + $process.StandardOutput.ReadLine() | Should Be "3" + $process.StandardInput.Close() + $process.StandardOutput.ReadToEnd() | Should Be "PS> " + EnsureChildHasExited $process + } + + It "Interactive redirected input w/ initial command" { + $si = NewProcessStartInfo "-noprofile -noexit ""`$function:prompt = { 'PS> ' }""" -RedirectStdIn $process = RunPowerShell $si $process.StandardInput.Write("1+1`n") $process.StandardOutput.ReadLine() | Should Be "PS> 1+1" @@ -109,7 +181,7 @@ Describe "ConsoleHost unit tests" -Tag 'Slow' { EnsureChildHasExited $process } - It "Redirected input explicit prompting" -Pending:$IsCore { + It "Redirected input explicit prompting (-File -)" { $si = NewProcessStartInfo "-noprofile -File -" -RedirectStdIn $process = RunPowerShell $si $process.StandardInput.Write("`$function:prompt = { 'PS> ' }`n") @@ -122,7 +194,7 @@ Describe "ConsoleHost unit tests" -Tag 'Slow' { EnsureChildHasExited $process } - It "Redirected input no prompting" -Pending:$IsCore { + It "Redirected input no prompting (-Command -)" { $si = NewProcessStartInfo "-noprofile -" -RedirectStdIn $process = RunPowerShell $si $process.StandardInput.Write("1+1`n") @@ -131,8 +203,8 @@ Describe "ConsoleHost unit tests" -Tag 'Slow' { EnsureChildHasExited $process } - It "Redirected input w/ nested prompt" -Pending:$IsCore { - $si = NewProcessStartInfo "-noprofile ""`$function:prompt = { 'PS' + ('>'*(`$nestedPromptLevel+1)) + ' ' }""" -RedirectStdIn + It "Redirected input w/ nested prompt" { + $si = NewProcessStartInfo "-noprofile -noexit ""`$function:prompt = { 'PS' + ('>'*(`$nestedPromptLevel+1)) + ' ' }""" -RedirectStdIn $process = RunPowerShell $si $process.StandardInput.Write("`$host.EnterNestedPrompt()`n") $process.StandardOutput.ReadLine() | Should Be "PS> `$host.EnterNestedPrompt()"