diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/CommandLineParameterParser.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/CommandLineParameterParser.cs index ea5b8dfdf..e2695a7c8 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/CommandLineParameterParser.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/CommandLineParameterParser.cs @@ -354,7 +354,7 @@ namespace Microsoft.PowerShell switchKey = switchKey.Substring(1); // chop off the second dash so we're agnostic wrt specifying - or -- - if (SpecialCharacters.IsDash(switchKey[0])) + if (!String.IsNullOrEmpty(switchKey) && SpecialCharacters.IsDash(switchKey[0])) { switchKey = switchKey.Substring(1); } @@ -483,7 +483,10 @@ namespace Microsoft.PowerShell string exceptionMessage = null; try { - file = Path.GetFullPath(args[i]); + // Normalize slashes + file = args[i].Replace(StringLiterals.AlternatePathSeparator, + StringLiterals.DefaultPathSeparator); + file = Path.GetFullPath(file); } catch (Exception e) { diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleControl.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleControl.cs index 0a7705332..e34d05988 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleControl.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleControl.cs @@ -1,4 +1,4 @@ -#if !PORTABLE +#if !LINUX /********************************************************************++ Copyright (c) Microsoft Corporation. All rights reserved. --********************************************************************/ diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs index 886b1539f..e8363a6c8 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs @@ -293,7 +293,7 @@ namespace Microsoft.PowerShell /// /// /// -#if PORTABLE +#if LINUX private static void MyBreakHandler(object sender, ConsoleCancelEventArgs args) { // Set the Cancel property to true to prevent the process from terminating. @@ -461,7 +461,7 @@ namespace Microsoft.PowerShell // call the console APIs directly, instead of ui.rawui.FlushInputHandle, as ui may be finalized // already if this thread is lagging behind the main thread. -#if !PORTABLE +#if !LINUX ConsoleHandle handle = ConsoleControl.GetConioDeviceHandle(); ConsoleControl.FlushConsoleInputBuffer(handle); #endif @@ -1059,7 +1059,7 @@ namespace Microsoft.PowerShell private void BindBreakHandler() { -#if PORTABLE +#if LINUX Console.CancelKeyPress += new ConsoleCancelEventHandler(MyBreakHandler); #else breakHandlerGcHandle = GCHandle.Alloc(new ConsoleControl.BreakHandler(MyBreakHandler)); @@ -1118,7 +1118,7 @@ namespace Microsoft.PowerShell { if (!isDisposed) { -#if !PORTABLE +#if !LINUX Dbg.Assert(breakHandlerGcHandle != null, "break handler should be set"); ConsoleControl.RemoveBreakHandler(); breakHandlerGcHandle.Free(); @@ -2867,7 +2867,7 @@ namespace Microsoft.PowerShell /// private RunspaceRef runspaceRef; -#if !PORTABLE +#if !LINUX private GCHandle breakHandlerGcHandle; #endif private System.Threading.Thread breakHandlerThread; diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostRawUserInterface.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostRawUserInterface.cs index 04cc4436f..2c260fb47 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostRawUserInterface.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostRawUserInterface.cs @@ -1,4 +1,4 @@ -#if !PORTABLE +#if !LINUX /********************************************************************++ Copyright (c) Microsoft Corporation. All rights reserved. --********************************************************************/ @@ -1541,7 +1541,14 @@ namespace Microsoft.PowerShell /// public override ConsoleColor BackgroundColor { - get { return Console.BackgroundColor; } + get + { + // Console can return UnknownColor, a private enum, equivalent + // to -1. When this is a case, map it instead to our default. + return Console.BackgroundColor == (ConsoleColor)(-1) + ? defaultBackground + : Console.BackgroundColor; + } set { Console.BackgroundColor = value; } } @@ -1549,32 +1556,23 @@ namespace Microsoft.PowerShell private static Size WrapSize = new Size(80, 40); /// - /// Gets or sets the size of the host buffer. In this example the - /// buffer size is adapted from the Console buffer size members. + /// Gets or sets the size of the host buffer. /// public override Size BufferSize { get { - // When stdout is redirected, the buffer size is (0, 0); - // however, this is still queried for use in formatting, so we - // provide the WrapSize. - if (Console.IsOutputRedirected) - { - return WrapSize; - } - else - { - return new Size(Console.BufferWidth, Console.BufferHeight); - } + // Console can return zero when a pseduo-TTY is allocated, which + // is useless for us. Instead, map to the wrap size. + return Console.BufferWidth == 0 || Console.BufferHeight == 0 + ? WrapSize + : new Size(Console.BufferWidth, Console.BufferHeight); } set { Console.SetBufferSize(value.Width, value.Height); } } /// - /// Gets or sets the cursor position. In this example this - /// functionality is not needed so the property throws a - /// NotImplementException exception. + /// Gets or sets the cursor position. /// public override Coordinates CursorPosition { @@ -1583,23 +1581,31 @@ namespace Microsoft.PowerShell } /// - /// Gets or sets the size of the displayed cursor. In this example - /// the cursor size is taken directly from the Console.CursorSize - /// property. + /// Gets or sets the size of the displayed cursor. + /// This maps to the corresponding Console.CursorSize property. /// public override int CursorSize { + // Future porting note: this API throws on Windows when output is + // redirected, but never throws on Unix because it's fake. get { return Console.CursorSize; } set { Console.CursorSize = value; } } /// /// Gets or sets the foreground color of the displayed text. - /// This maps to the corresponding Console.ForgroundColor property. + /// This maps to the corresponding Console.ForegroundColor property. /// public override ConsoleColor ForegroundColor { - get { return Console.ForegroundColor; } + get + { + // Console can return UnknownColor, a private enum, equivalent + // to -1. When this is a case, map it instead to our default. + return Console.ForegroundColor == (ConsoleColor)(-1) + ? defaultForeground + : Console.ForegroundColor; + } set { Console.ForegroundColor = value; } } @@ -1613,32 +1619,37 @@ namespace Microsoft.PowerShell } /// - /// Gets the dimensions of the largest window that could be - /// rendered in the current display, if the buffer was at the least - /// that large. This example uses the Console.LargestWindowWidth and - /// Console.LargestWindowHeight properties to determine the returned - /// value of this property. + /// Gets the dimensions of the largest window that could be rendered in + /// the current display, if the buffer was at the least that large. + /// This maps to the MaxWindowSize. /// public override Size MaxPhysicalWindowSize { - get { return new Size(Console.LargestWindowWidth, Console.LargestWindowHeight); } + get { return MaxWindowSize; } } /// - /// Gets the dimentions of the largest window size that can be - /// displayed. This example uses the Console.LargestWindowWidth and - /// console.LargestWindowHeight properties to determine the returned + /// Gets the dimensions of the largest window size that can be + /// displayed. This maps to the Console.LargestWindowWidth and + /// Console.LargestWindowHeight properties to determine the returned /// value of this property. /// public override Size MaxWindowSize { - get { return new Size(Console.LargestWindowWidth, Console.LargestWindowHeight); } + get + { + // Console can return zero when a pseduo-TTY is allocated, which + // is useless for us. Instead, map to the wrap size. + return Console.LargestWindowWidth == 0 || Console.LargestWindowHeight == 0 + ? WrapSize + : new Size(Console.LargestWindowWidth, Console.LargestWindowHeight); + } } /// - /// Gets or sets the position of the displayed window. This example - /// uses the Console window position APIs to determine the returned - /// value of this property. + /// Gets or sets the position of the displayed window. This maps to the + /// Console window position APIs to determine the returned value of this + /// property. /// public override Coordinates WindowPosition { @@ -1655,14 +1666,11 @@ namespace Microsoft.PowerShell { get { - if (Console.IsOutputRedirected) - { - return WrapSize; - } - else - { - return new Size(Console.WindowWidth, Console.WindowHeight); - } + // Console can return zero when a pseduo-TTY is allocated, which + // is useless for us. Instead, map to the wrap size. + return Console.WindowWidth == 0 || Console.WindowHeight == 0 + ? WrapSize + : new Size(Console.WindowWidth, Console.WindowHeight); } set { Console.SetWindowSize(value.Width, value.Height); } } @@ -1680,20 +1688,9 @@ namespace Microsoft.PowerShell { get { - // In Unix/Linux systems, Console.Title current results in a not-implemented - // exception. In that case, we return a cached copy of title that was set earlier. - // Obviously, this will not work if: 1) Title was never set in PowerShell, or 2) - // one sets the windows's title outside of PowerShell. - string result; - try - { - result = Console.Title; - } - catch (PlatformNotSupportedException) - { - return title; - } - return result; + // Console throws an exception on Unix platforms, so we handle + // caching and returning the Window title ourselves. + return Platform.IsWindows ? Console.Title : title; } set @@ -1704,11 +1701,14 @@ namespace Microsoft.PowerShell } /// - /// This API resets the input buffer. In this example this - /// functionality is not needed so the method returns nothing. + /// This API resets the input buffer. /// public override void FlushInputBuffer() { + if (!Console.IsInputRedirected) + { + Console.OpenStandardInput().Flush(); + } } /// diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterface.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterface.cs index a7db0f5bf..8dbf99f24 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterface.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHostUserInterface.cs @@ -14,7 +14,7 @@ using System.Management.Automation.Internal; using System.Management.Automation.Host; using System.Security; using Dbg = System.Management.Automation.Diagnostics; -#if !PORTABLE +#if !LINUX using ConsoleHandle = Microsoft.Win32.SafeHandles.SafeFileHandle; #endif @@ -61,7 +61,7 @@ namespace Microsoft.PowerShell this.parent = parent; this.rawui = new ConsoleHostRawUserInterface(this); -#if PORTABLE +#if LINUX this._supportsVirtualTerminal = true; #else try @@ -285,7 +285,7 @@ namespace Microsoft.PowerShell private object ReadLineSafe(bool isSecureString, char? printToken) { -#if PORTABLE +#if LINUX throw new PlatformNotSupportedException("Cannot read secure strings!"); #else // Don't lock (instanceLock) in here -- the caller needs to do that... @@ -411,7 +411,7 @@ namespace Microsoft.PowerShell #endif } -#if !PORTABLE +#if !LINUX /// /// @@ -560,7 +560,7 @@ namespace Microsoft.PowerShell internal void WriteToConsole(string value, bool transcribeResult) { -#if !PORTABLE +#if !LINUX ConsoleHandle handle = ConsoleControl.GetActiveScreenBufferHandle(); // Ensure that we're in the proper line-output mode. We don't lock here as it does not matter if we @@ -583,7 +583,7 @@ namespace Microsoft.PowerShell // This is atomic, so we don't lock here... -#if !PORTABLE +#if !LINUX ConsoleControl.WriteConsole(handle, value); #else Console.Out.Write(value); @@ -1637,7 +1637,7 @@ namespace Microsoft.PowerShell private string ReadLineFromConsole(bool endOnTab, string initialContent, bool calledFromPipeline, ref string restOfLine, ref ReadLineResult result) { -#if PORTABLE +#if LINUX return ReadLineFromFile(initialContent); #else ConsoleHandle handle = ConsoleControl.GetConioDeviceHandle(); @@ -1771,7 +1771,7 @@ namespace Microsoft.PowerShell /// /// the cursor position where 'tab' is hit /// -#if !PORTABLE +#if !LINUX private char GetCharacterUnderCursor(Coordinates cursorPosition) { Rectangle region = new Rectangle(0, cursorPosition.Y, RawUI.BufferSize.Width - 1, cursorPosition.Y); @@ -1840,7 +1840,7 @@ namespace Microsoft.PowerShell ReadLineResult rlResult = ReadLineResult.endedOnEnter; -#if !PORTABLE +#if !LINUX ConsoleHandle handle = ConsoleControl.GetActiveScreenBufferHandle(); string lastCompletion = ""; @@ -1874,7 +1874,7 @@ namespace Microsoft.PowerShell break; } -#if PORTABLE // Portable code only ends on enter (or no input), so tab is not processed +#if LINUX // Portable code only ends on enter (or no input), so tab is not processed throw new PlatformNotSupportedException("This readline state is unsupported in portable code!"); #else @@ -2000,7 +2000,7 @@ namespace Microsoft.PowerShell return input; } -#if !PORTABLE +#if !LINUX private void SendLeftArrows(int length) { var inputs = new ConsoleControl.INPUT[length * 2]; diff --git a/src/Microsoft.PowerShell.ConsoleHost/project.json b/src/Microsoft.PowerShell.ConsoleHost/project.json index 054135941..297cdfa42 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/project.json +++ b/src/Microsoft.PowerShell.ConsoleHost/project.json @@ -46,6 +46,15 @@ ] }, + "configurations": { + "Linux": { + "buildOptions": { + "define": [ "LINUX" ] + } + } + }, + + "dependencies": { "Microsoft.PowerShell.PSReadLine": "1.0.0-*", "Microsoft.PowerShell.Commands.Diagnostics": "1.0.0-*", diff --git a/src/Microsoft.PowerShell.PSReadLine/ReadLine.cs b/src/Microsoft.PowerShell.PSReadLine/ReadLine.cs index 58a9591db..aabf5a46a 100644 --- a/src/Microsoft.PowerShell.PSReadLine/ReadLine.cs +++ b/src/Microsoft.PowerShell.PSReadLine/ReadLine.cs @@ -258,6 +258,14 @@ namespace Microsoft.PowerShell public static string ReadLine(Runspace runspace, EngineIntrinsics engineIntrinsics) { var console = _singleton._console; + + // If either stdin or stdout is redirected, PSReadline doesn't really work, so throw + // and let PowerShell call Console.ReadLine or do whatever else it decides to do. + if (Console.IsInputRedirected || Console.IsOutputRedirected) + { + throw new NotSupportedException(); + } + #if CORECLR _singleton._prePSReadlineControlCMode = Console.TreatControlCAsInput; #else diff --git a/test/powershell/Host/Base-Directory.Tests.ps1 b/test/powershell/Host/Base-Directory.Tests.ps1 index b25c9203e..5fb9bbbf2 100644 --- a/test/powershell/Host/Base-Directory.Tests.ps1 +++ b/test/powershell/Host/Base-Directory.Tests.ps1 @@ -21,11 +21,7 @@ Describe "Configuration file locations" { $expectedReadline = [IO.Path]::Combine($env:HOME, ".local", "share", "powershell", "PSReadLine", "ConsoleHost_history.txt") } - if ($env:TRAVIS_OS_NAME -eq "osx") { - $ItArgs = @{ pending = $true } - } else { - $ItArgs = @{} - } + $ItArgs = @{} } BeforeEach { @@ -65,8 +61,6 @@ Describe "Configuration file locations" { # Using It @ItArgs, we automatically skip on Windows for all these tests if ($IsWindows) { $ItArgs = @{ skip = $true } - } elseif ($env:TRAVIS_OS_NAME -eq "osx") { - $ItArgs = @{ pending = $true } } else { $ItArgs = @{} } diff --git a/test/powershell/Host/ConsoleHost.Tests.ps1 b/test/powershell/Host/ConsoleHost.Tests.ps1 index e1854e3ab..94e66c6d9 100644 --- a/test/powershell/Host/ConsoleHost.Tests.ps1 +++ b/test/powershell/Host/ConsoleHost.Tests.ps1 @@ -1,60 +1,10 @@ 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" - Context "CommandLine" { - It "simple -args" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { - & $powershell -noprofile { $args[0] } -args "hello world" | Should Be "hello world" - } - - It "array -args" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { - & $powershell -noprofile { $args[0] } -args 1,(2,3) | Should Be 1 - (& $powershell -noprofile { $args[1] } -args 1,(2,3))[1] | Should Be 3 - } - foreach ($x in "--help", "-help", "-h", "-?", "--he", "-hel", "--HELP", "-hEl") { - It "Accepts '$x' as a parameter for help" { - & $powershell -noprofile $x | ?{ $_ -match "PowerShell[.exe] -Help | -? | /?" } | Should Not BeNullOrEmpty - } - } - - It "Should accept a Base64 encoded command" { - $commandString = "Get-Location" - $encodedCommand = [System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($commandString)) - # We don't compare to `Get-Location` directly because object and formatted output comparisons are difficult - $expected = & $powershell -noprofile -command $commandString - $actual = & $powershell -noprofile -EncodedCommand $encodedCommand - $actual | Should Be $expected - } - - } - - Context "Pipe to/from powershell" { - $p = [PSCustomObject]@{X=10;Y=20} - - It "xml input" { - $p | & $powershell -noprofile { $input | Foreach-Object {$a = 0} { $a += $_.X + $_.Y } { $a } } | Should Be 30 - $p | & $powershell -noprofile -inputFormat xml { $input | Foreach-Object {$a = 0} { $a += $_.X + $_.Y } { $a } } | Should Be 30 - } - - It "text input" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { - # Join (multiple lines) and remove whitespace (we don't care about spacing) to verify we converted to string (by generating a table) - $p | & $powershell -noprofile -inputFormat text { -join ($input -replace "\s","") } | Should Be "XY--1020" - } - - It "xml output" { - & $powershell -noprofile { [PSCustomObject]@{X=10;Y=20} } | Foreach-Object {$a = 0} { $a += $_.X + $_.Y } { $a } | Should Be 30 - & $powershell -noprofile -outputFormat xml { [PSCustomObject]@{X=10;Y=20} } | Foreach-Object {$a = 0} { $a += $_.X + $_.Y } { $a } | Should Be 30 - } - - It "text output" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { - # Join (multiple lines) and remove whitespace (we don't care about spacing) to verify we converted to string (by generating a table) - -join (& $powershell -noprofile -outputFormat text { [PSCustomObject]@{X=10;Y=20} }) -replace "\s","" | Should Be "XY--1020" - } - } - - Context "Redirected standard handles" { function NewProcessStartInfo([string]$CommandLine, [switch]$RedirectStdIn) { return [ProcessStartInfo]@{ @@ -84,19 +34,141 @@ Describe "ConsoleHost unit tests" -Tag 'Slow' { $process.Kill() } } + } - It "Simple redirected output" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + Context "CommandLine" { + It "simple -args" { + & $powershell -noprofile { $args[0] } -args "hello world" | Should Be "hello world" + } + + It "array -args" { + & $powershell -noprofile { $args[0] } -args 1,(2,3) | Should Be 1 + (& $powershell -noprofile { $args[1] } -args 1,(2,3))[1] | Should Be 3 + } + foreach ($x in "--help", "-help", "-h", "-?", "--he", "-hel", "--HELP", "-hEl") { + It "Accepts '$x' as a parameter for help" { + & $powershell -noprofile $x | ?{ $_ -match "PowerShell[.exe] -Help | -? | /?" } | Should Not BeNullOrEmpty + } + } + + It "Should accept a Base64 encoded command" { + $commandString = "Get-Location" + $encodedCommand = [System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($commandString)) + # We don't compare to `Get-Location` directly because object and formatted output comparisons are difficult + $expected = & $powershell -noprofile -command $commandString + $actual = & $powershell -noprofile -EncodedCommand $encodedCommand + $actual | Should Be $expected + } + + } + + Context "Pipe to/from powershell" { + $p = [PSCustomObject]@{X=10;Y=20} + + It "xml input" { + $p | & $powershell -noprofile { $input | Foreach-Object {$a = 0} { $a += $_.X + $_.Y } { $a } } | Should Be 30 + $p | & $powershell -noprofile -inputFormat xml { $input | Foreach-Object {$a = 0} { $a += $_.X + $_.Y } { $a } } | Should Be 30 + } + + It "text input" { + # Join (multiple lines) and remove whitespace (we don't care about spacing) to verify we converted to string (by generating a table) + $p | & $powershell -noprofile -inputFormat text { -join ($input -replace "\s","") } | Should Be "XY--1020" + } + + It "xml output" { + & $powershell -noprofile { [PSCustomObject]@{X=10;Y=20} } | Foreach-Object {$a = 0} { $a += $_.X + $_.Y } { $a } | Should Be 30 + & $powershell -noprofile -outputFormat xml { [PSCustomObject]@{X=10;Y=20} } | Foreach-Object {$a = 0} { $a += $_.X + $_.Y } { $a } | Should Be 30 + } + + It "text output" { + # Join (multiple lines) and remove whitespace (we don't care about spacing) to verify we converted to string (by generating a table) + -join (& $powershell -noprofile -outputFormat text { [PSCustomObject]@{X=10;Y=20} }) -replace "\s","" | Should Be "XY--1020" + } + } + + 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()" diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Custom.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Custom.Tests.ps1 index 64afb70ff..3645f9758 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Custom.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Custom.Tests.ps1 @@ -58,7 +58,7 @@ Describe "Format-Custom DRT basic functionality" -Tags DRT{ } "@ - It "Format-Custom with subobject should work" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "Format-Custom with subobject should work" { $expectResult1 = "this is the name" $expectResult2 = "this is the name of the sub object" $testObject = @{} @@ -74,7 +74,7 @@ Describe "Format-Custom DRT basic functionality" -Tags DRT{ $result | Should Match "two" } - It "Format-Custom with Tree Object should work" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "Format-Custom with Tree Object should work" { $expectedResult=@" class MyContainer1 { @@ -203,7 +203,7 @@ class MyContainer1 $result | Should Be $expectedResult } - It "Format-Custom with Empty Data Tree Object should work" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "Format-Custom with Empty Data Tree Object should work" { $expectedResult=@" class MyContainer1 { @@ -225,7 +225,7 @@ class MyContainer1 $result | Should Be $expectedResult } - It "Format-Custom with Back Pointers Tree Object should work" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "Format-Custom with Back Pointers Tree Object should work" { $expectedResult=@" class MyContainer1 { @@ -268,7 +268,7 @@ class MyContainer1 $result | Should Be $expectedResult } - It "Format-Custom with Leaf Only Data should work" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "Format-Custom with Leaf Only Data should work" { $expectedResult=@" class MyLeaf1 { diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-List.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-List.Tests.ps1 index 60ccdf9a5..3bc9d4dcf 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-List.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-List.Tests.ps1 @@ -20,7 +20,7 @@ Describe "Format-List" { $actual | Should Be $expected } - It "Should produce the expected output" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "Should produce the expected output" { $expected = "${nl}${nl}testName : testValue${nl}${nl}${nl}${nl}" $in = New-Object PSObject Add-Member -InputObject $in -MemberType NoteProperty -Name testName -Value testValue @@ -68,7 +68,7 @@ Describe "Format-List" { } Describe "Format-List DRT basic functionality" -Tags DRT{ - It "Format-List with array should work"-Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "Format-List with array should work" { $al = (0..255) $info = @{} $info.array = $al @@ -106,7 +106,7 @@ Describe "Format-List DRT basic functionality" -Tags DRT{ $result.Trim() | Should BeNullOrEmpty } - It "Format-List with complex object for End-To-End should work" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "Format-List with complex object for End-To-End should work" { Add-Type -TypeDefinition "public enum MyDayOfWeek{Sun,Mon,Tue,Wed,Thr,Fri,Sat}" $eto = [MyDayOfWeek]::New() $info = @{} @@ -125,7 +125,7 @@ Describe "Format-List DRT basic functionality" -Tags DRT{ $result | Should Match "Value : {1, 2, 3, 4}" } - It "Format-List with multiple same class object should work" -Pending:($env:TRAVIS_OS_NAME -eq "osx"){ + It "Format-List with multiple same class object should work"{ Add-Type -TypeDefinition "public class TestClass{public TestClass(string name,int length){Name = name;Length = length;}public string Name;public int Length;}" $testobjects = [TestClass]::New('name1',1),[TestClass]::New('name2',2),[TestClass]::New('name3',3) $result = $testobjects|Format-List|Out-String @@ -137,7 +137,7 @@ Describe "Format-List DRT basic functionality" -Tags DRT{ $result | Should Match "Length : 3" } - It "Format-List with multiple different class object should work" -Pending:($env:TRAVIS_OS_NAME -eq "osx"){ + It "Format-List with multiple different class object should work"{ Add-Type -TypeDefinition "public class TestClass{public TestClass(string name,int length){Name = name;Length = length;}public string Name;public int Length;}" Add-Type -TypeDefinition "public class TestClass2{public TestClass2(string name,string value,int length){Name = name;Value = value; Length = length;}public string Name;public string Value;public int Length;}" $testobjects = [TestClass]::New('name1',1),[TestClass2]::New('name2',"value2",2),[TestClass]::New('name3',3) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Table.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Table.Tests.ps1 index 5f85a76f9..b56cb809d 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Table.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Table.Tests.ps1 @@ -43,7 +43,7 @@ Describe "Format-Table DRT Unit Tests" -Tags DRT{ } } - It "Format-Table with array should work" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "Format-Table with array should work" { $al = (0..255) $info = @{} $info.array = $al @@ -51,7 +51,7 @@ Describe "Format-Table DRT Unit Tests" -Tags DRT{ $result | Should Match "array\s+{0, 1, 2, 3...}" } - It "Format-Table with Negative Count should work" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "Format-Table with Negative Count should work" { $FormatEnumerationLimit = -1 $result = Format-Table -inputobject @{'test'= 1, 2} $resultStr = $result|Out-String @@ -66,21 +66,21 @@ Describe "Format-Table DRT Unit Tests" -Tags DRT{ $resultStr | Should Match "test\s+{...}" } - It "Format-Table with Less Count should work" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "Format-Table with Less Count should work" { $FormatEnumerationLimit = 1 $result = Format-Table -inputobject @{'test'= 1, 2} $resultStr = $result|Out-String $resultStr | Should Match "test\s+{1...}" } - It "Format-Table with More Count should work" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "Format-Table with More Count should work" { $FormatEnumerationLimit = 10 $result = Format-Table -inputobject @{'test'= 1, 2} $resultStr = $result|Out-String $resultStr | Should Match "test\s+{1, 2}" } - It "Format-Table with Equal Count should work" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "Format-Table with Equal Count should work" { $FormatEnumerationLimit = 2 $result = Format-Table -inputobject @{'test'= 1, 2} $resultStr = $result|Out-String @@ -104,14 +104,14 @@ Describe "Format-Table DRT Unit Tests" -Tags DRT{ $resultStr | Should Match "test\s+{1, 2}" } - It "Format-Table with new line should work" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "Format-Table with new line should work" { $info = @{} $info.name = "1\n2" $result = $info|Format-Table|Out-String $result | Should Match "name\s+1.+2" } - It "Format-Table with ExposeBug920454 should work" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "Format-Table with ExposeBug920454 should work" { $IP1 = [System.Net.IPAddress]::Parse("1.1.1.1") $IP2 = [System.Net.IPAddress]::Parse("4fde:0000:0000:0002:0022:f376:255.59.171.63") $IPs = New-Object System.Collections.ArrayList @@ -123,7 +123,7 @@ Describe "Format-Table DRT Unit Tests" -Tags DRT{ $result | Should Match "test\s+{1.1.1.1, 4fde::2:22:f376:ff3b:ab3f}" } - It "Format-Table with Autosize should work" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "Format-Table with Autosize should work" { $IP1 = [PSCustomObject]@{'name'='Bob';'size'=1234;'booleanValue'=$true;} $IP2 = [PSCustomObject]@{'name'='Jim';'size'=5678;'booleanValue'=$false;} $IPs = New-Object System.Collections.ArrayList @@ -176,7 +176,7 @@ Describe "Format-Table DRT Unit Tests" -Tags DRT{ $result | Should BeNullOrEmpty } - It "Format-Table with complex object for End-To-End should work" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "Format-Table with complex object for End-To-End should work" { Add-Type -TypeDefinition "public enum MyDayOfWeek{Sun,Mon,Tue,Wed,Thr,Fri,Sat}" $eto = New-Object MyDayOfWeek $info = @{} @@ -191,7 +191,7 @@ Describe "Format-Table DRT Unit Tests" -Tags DRT{ $result | Should Match "enumerableTestObject\s+Sun" } - It "Format-Table with Expand Enumerable should work" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "Format-Table with Expand Enumerable should work" { $obj1 = "x 0","y 0" $obj2 = "x 1","y 1" $objs = New-Object System.Collections.ArrayList diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Wide.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Wide.Tests.ps1 index c3a51491a..f588870db 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Wide.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Format-Wide.Tests.ps1 @@ -40,7 +40,7 @@ Describe "Format-Wide" { } Describe "Format-Wide DRT basic functionality" -Tags DRT{ - It "Format-Wide with array should work" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "Format-Wide with array should work" { $al = (0..255) $info = @{} $info.array = $al @@ -80,7 +80,7 @@ Describe "Format-Wide DRT basic functionality" -Tags DRT{ $result | Should Match "Line2" } - It "Format-Wide with complex object for End-To-End should work" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "Format-Wide with complex object for End-To-End should work" { Add-Type -TypeDefinition "public enum MyDayOfWeek{Sun,Mon,Tue,Wed,Thr,Fri,Sat}" $eto = New-Object MyDayOfWeek $info = @{} @@ -95,7 +95,7 @@ Describe "Format-Wide DRT basic functionality" -Tags DRT{ $result | Should Match "enumerableTestObject" } - It "Format-Wide with multiple same class object with grouping should work" -Pending:($env:TRAVIS_OS_NAME -eq "osx"){ + It "Format-Wide with multiple same class object with grouping should work"{ Add-Type -TypeDefinition "public class TestGroupingClass{public TestGroupingClass(string name,int length){Name = name;Length = length;}public string Name;public int Length;public string GroupingKey;}" $testobject1 = [TestGroupingClass]::New('name1',1) $testobject1.GroupingKey = "foo" diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-Date.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-Date.Tests.ps1 index f43021dcc..69f113fb7 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-Date.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-Date.Tests.ps1 @@ -12,7 +12,7 @@ Describe "Get-Date DRT Unit Tests" -Tags DRT { $result.Millisecond | Should be 200 } - It "using -displayhint produces the correct output" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "using -displayhint produces the correct output" { $d = Get-date -Date:"Jan 1, 2020" -DisplayHint Date | Out-String $d.Trim() | Should be "Wednesday, January 1, 2020" } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Out-File.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Out-File.Tests.ps1 index 75732b9d5..c3dafc914 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Out-File.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Out-File.Tests.ps1 @@ -52,7 +52,7 @@ Describe "Out-File" { { Out-File -FilePath $testfile -InputObject $inObject } | Should Not Throw } - It "Should not overwrite when the noclobber switch is used" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "Should not overwrite when the noclobber switch is used" { Out-File -FilePath $testfile -InputObject $inObject @@ -67,7 +67,7 @@ Describe "Out-File" { $actual[3] | Should Match "some test text" } - It "Should Append a new line when the append switch is used" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "Should Append a new line when the append switch is used" { { Out-File -FilePath $testfile -InputObject $inObject } | Should Not Throw { Out-File -FilePath $testfile -InputObject $inObject -Append } | Should Not Throw @@ -101,7 +101,7 @@ Describe "Out-File" { } - It "Should allow the cmdlet to overwrite an existing read-only file" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "Should allow the cmdlet to overwrite an existing read-only file" { # create a read-only text file { Out-File -FilePath $testfile -InputObject $inObject } | Should Not Throw Set-ItemProperty -Path $testfile -Name IsReadOnly -Value $true diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Out-String.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Out-String.Tests.ps1 index c4c5c5133..841a4ffe6 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Out-String.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Out-String.Tests.ps1 @@ -1,6 +1,6 @@ Describe "Out-String DRT Unit Tests" -Tags DRT{ - It "check display of properties with names containing wildcard characters" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "check display of properties with names containing wildcard characters" { $results = new-object psobject | add-member -passthru noteproperty 'name with square brackets: [0]' 'myvalue' | out-string $results.Length | Should BeGreaterThan 1 $results.GetType() | Should Be string diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Set-Variable.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Set-Variable.Tests.ps1 index 18e04f887..9b12fb010 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Set-Variable.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Set-Variable.Tests.ps1 @@ -208,7 +208,7 @@ Describe "Set-Variable" { $testVar | Should Be $testValue } - It "Should be able to pipe object properties to output using the PassThru switch" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "Should be able to pipe object properties to output using the PassThru switch" { $in = Set-Variable -Name testVar -Value "test" -Description "test description" -PassThru $output = $in | Format-List -Property Description | Out-String diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Host.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Host.Tests.ps1 index 2395d91bf..ce59a43b1 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Host.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Host.Tests.ps1 @@ -1,22 +1,18 @@ -Describe "Write-Host DRT Unit Tests" -Tags DRT{ +Describe "Write-Host DRT Unit Tests" -Tags DRT { + + BeforeAll { + $powershell = Join-Path -Path $PsHome -ChildPath "powershell" + } + + $testData = @( @{ Name = 'NoNewline';Command = "Write-Host a,b -Separator ',' -ForegroundColor Yellow -BackgroundColor DarkBlue -NoNewline"; returnValue = "a,b" } @{ Name = 'Separator';Command = "Write-Host a,b,c -Separator '+'"; returnValue = "a+b+c" } ) - - It "write-Host works with '' switch" -TestCases $testData -Pending:$IsOSX { - param($Command, $returnValue) - If($IsLinux) - { - $content = powershell -noprofile -command $Command - } - - If ($IsWindows) - { - $content = powershell.exe -noprofile -command $Command - } + It "write-Host works with '' switch" -TestCases $testData -Pending:$IsOSX { + param($Command, $returnValue) - $content | Should Be $returnValue + & $powershell -noprofile $Command | Should Be $returnValue } -} \ No newline at end of file +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Stream.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Stream.Tests.ps1 index a7dc077c8..9f0bff4c4 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Stream.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Stream.Tests.ps1 @@ -28,13 +28,13 @@ Describe "Stream writer tests" { # These tests validate that a stream is actually being written to by redirecting the output of that stream AfterEach { Remove-Item $targetfile } - It "Should write warnings to the warning stream" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "Should write warnings to the warning stream" { Write-Warning "Test Warning" 3>&1 > $targetfile Get-Content $targetfile | Should Be "Test Warning" } - It "Should write error messages to the error stream" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "Should write error messages to the error stream" { Write-Error "Testing Error" 2>&1 > $targetfile $result = Get-OutputResults $targetfile @@ -42,7 +42,7 @@ Describe "Stream writer tests" { $result -match ": Testing Error" | Should Be $true } - It "Should write debug messages to the debug stream" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "Should write debug messages to the debug stream" { Write-Messages -Debug -EA SilentlyContinue 5>&1 > $targetfile $result = Get-OutputResults $targetfile @@ -51,7 +51,7 @@ Describe "Stream writer tests" { $result -match "Debug Message" | Should Be $true } - It "Should write messages to the verbose stream" -Pending:($env:TRAVIS_OS_NAME -eq "osx") { + It "Should write messages to the verbose stream" { Write-Messages -Verbose 4>&1 > $targetfile $result = Get-OutputResults $targetfile