From 18d5037ad2a97db7b306171a4ba4be0dcce91e5e Mon Sep 17 00:00:00 2001 From: "Joel Sallow (/u/ta11ow)" <32407840+vexx32@users.noreply.github.com> Date: Wed, 13 Mar 2019 04:54:12 -0400 Subject: [PATCH] Fix -NoEnumerate behaviour in Write-Output (#9069) Fix is to preserve input collection type in output. The regression was caused by #2038 --- .../commands/utility/Write-Object.cs | 29 ++----- .../Write-Output.Tests.ps1 | 76 +++++++++++-------- 2 files changed, 49 insertions(+), 56 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Write-Object.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Write-Object.cs index f0cd5d4b2..376f30f51 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Write-Object.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/Write-Object.cs @@ -12,49 +12,32 @@ namespace Microsoft.PowerShell.Commands [Cmdlet(VerbsCommunications.Write, "Output", HelpUri = "https://go.microsoft.com/fwlink/?LinkID=113427", RemotingCapability = RemotingCapability.None)] public sealed class WriteOutputCommand : PSCmdlet { - private PSObject[] _inputObjects = null; - /// /// Holds the list of objects to be written. /// [Parameter(Position = 0, Mandatory = true, ValueFromPipeline = true, ValueFromRemainingArguments = true)] [AllowNull] [AllowEmptyCollection] - public PSObject[] InputObject - { - get { return _inputObjects; } - - set { _inputObjects = value; } - } + public PSObject InputObject { get; set; } /// /// Prevents Write-Output from unravelling collections passed to the InputObject parameter. /// - [Parameter()] - public SwitchParameter NoEnumerate - { - get; - set; - } + [Parameter] + public SwitchParameter NoEnumerate { get; set; } /// /// This method implements the ProcessRecord method for Write-output command. /// protected override void ProcessRecord() { - if (_inputObjects == null) + if (InputObject == null) { - WriteObject(_inputObjects); + WriteObject(InputObject); return; } - bool enumerate = true; - if (NoEnumerate.IsPresent) - { - enumerate = false; - } - - WriteObject(_inputObjects, enumerate); + WriteObject(InputObject, !NoEnumerate.IsPresent); } } #endregion diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Output.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Output.Tests.ps1 index 648913ecd..08cc880a0 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Output.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Write-Output.Tests.ps1 @@ -18,60 +18,70 @@ Describe "Write-Output DRT Unit Tests" -Tags "CI" { It "Works with NoEnumerate switch" { $objectWritten = 1, 2.2, @("John", "Smith", 10), "abc" - [string]$s = Write-Output $objectWritten -NoEnumerate 6>&1 + [string]$s = Write-Output $objectWritten -NoEnumerate 6>&1 $s | Should -Be '1 2.2 System.Object[] abc' } + + It "Preserves the input collection type and contents with -NoEnumerate" { + $List = [System.Collections.Generic.List[string]]::new( [string[]]@("test", "one", "two") ) + $ObjectWritten = Write-Output $List -NoEnumerate + + $ObjectWritten.GetType() | Should -Be ([System.Collections.Generic.List[string]]) + $ObjectWritten[0] | Should -BeExactly "test" + $ObjectWritten[1] | Should -BeExactly "one" + $ObjectWritten[2] | Should -BeExactly "two" + } } Describe "Write-Output" -Tags "CI" { $testString = $testString Context "Input Tests" { - It "Should allow piped input" { - { $testString | Write-Output } | Should -Not -Throw - } + It "Should allow piped input" { + { $testString | Write-Output } | Should -Not -Throw + } - It "Should write output to the output stream when using piped input" { - $testString | Write-Output | Should -Be $testString - } + It "Should write output to the output stream when using piped input" { + $testString | Write-Output | Should -Be $testString + } - It "Should use inputobject switch" { - { Write-Output -InputObject $testString } | Should -Not -Throw - } + It "Should use inputobject switch" { + { Write-Output -InputObject $testString } | Should -Not -Throw + } - It "Should write output to the output stream when using inputobject switch" { - Write-Output -InputObject $testString | Should -Be $testString - } + It "Should write output to the output stream when using inputobject switch" { + Write-Output -InputObject $testString | Should -Be $testString + } - It "Should be able to write to a variable" { - Write-Output -InputObject $testString -OutVariable var - $var | Should -Be $testString - } + It "Should be able to write to a variable" { + Write-Output -InputObject $testString -OutVariable var + $var | Should -Be $testString + } } Context "Pipeline Command Tests" { - It "Should send object to the next command in the pipeline" { - Write-Output -InputObject (1+1) | Should -Be 2 - } + It "Should send object to the next command in the pipeline" { + Write-Output -InputObject (1 + 1) | Should -Be 2 + } - It "Should have the same result between inputobject switch and piped input" { - Write-Output -InputObject (1+1) | Should -Be 2 + It "Should have the same result between inputobject switch and piped input" { + Write-Output -InputObject (1 + 1) | Should -Be 2 - 1+1 | Write-Output | Should -Be 2 - } + 1 + 1 | Write-Output | Should -Be 2 + } } Context "Enumerate Objects" { - $enumerationObject = @(1,2,3) - It "Should see individual objects when not using the NoEnumerate switch" { - $singleCollection = $(Write-Output $enumerationObject| Measure-Object).Count + $enumerationObject = @(1, 2, 3) + It "Should see individual objects when not using the NoEnumerate switch" { + $singleCollection = $(Write-Output $enumerationObject| Measure-Object).Count - $singleCollection | Should -Be $enumerationObject.length - } + $singleCollection | Should -Be $enumerationObject.length + } - It "Should be able to treat a collection as a single object using the NoEnumerate switch" { - $singleCollection = $(Write-Output $enumerationObject -NoEnumerate | Measure-Object).Count + It "Should be able to treat a collection as a single object using the NoEnumerate switch" { + $singleCollection = $(Write-Output $enumerationObject -NoEnumerate | Measure-Object).Count - $singleCollection | Should -Be 1 - } + $singleCollection | Should -Be 1 + } } }