From 31f4d44565fe6b6abe3670cc7020030153e04422 Mon Sep 17 00:00:00 2001 From: Kyle H Date: Thu, 17 Sep 2020 14:40:11 -0500 Subject: [PATCH 01/33] `Get-Item directory -stream *` should work (v3) --- .../namespaces/FileSystemProvider.cs | 61 +++++++++++-------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/src/System.Management.Automation/namespaces/FileSystemProvider.cs b/src/System.Management.Automation/namespaces/FileSystemProvider.cs index be4b95dc935..9a321a6fd1b 100644 --- a/src/System.Management.Automation/namespaces/FileSystemProvider.cs +++ b/src/System.Management.Automation/namespaces/FileSystemProvider.cs @@ -1311,35 +1311,33 @@ protected override void GetItem(string path) // If we want to retrieve the file streams, retrieve them. if (retrieveStreams) { - if (!isContainer) + foreach (string desiredStream in dynamicParameters.Stream) { - foreach (string desiredStream in dynamicParameters.Stream) + // See that it matches the name specified + WildcardPattern p = WildcardPattern.Get(desiredStream, WildcardOptions.IgnoreCase | WildcardOptions.CultureInvariant); + bool foundStream = false; + + foreach (AlternateStreamData stream in AlternateDataStreamUtilities.GetStreams(result.FullName)) { - // See that it matches the name specified - WildcardPattern p = WildcardPattern.Get(desiredStream, WildcardOptions.IgnoreCase | WildcardOptions.CultureInvariant); - bool foundStream = false; + if (!p.IsMatch(stream.Stream)) + { continue; } - foreach (AlternateStreamData stream in AlternateDataStreamUtilities.GetStreams(result.FullName)) - { - if (!p.IsMatch(stream.Stream)) { continue; } + string outputPath = result.FullName + ":" + stream.Stream; + WriteItemObject(stream, outputPath, isContainer); + foundStream = true; + } - string outputPath = result.FullName + ":" + stream.Stream; - WriteItemObject(stream, outputPath, isContainer); - foundStream = true; - } + if ((!WildcardPattern.ContainsWildcardCharacters(desiredStream)) && (!foundStream)) + { + string errorMessage = StringUtil.Format( + FileSystemProviderStrings.AlternateDataStreamNotFound, desiredStream, result.FullName); + Exception e = new FileNotFoundException(errorMessage, result.FullName); - if ((!WildcardPattern.ContainsWildcardCharacters(desiredStream)) && (!foundStream)) - { - string errorMessage = StringUtil.Format( - FileSystemProviderStrings.AlternateDataStreamNotFound, desiredStream, result.FullName); - Exception e = new FileNotFoundException(errorMessage, result.FullName); - - WriteError(new ErrorRecord( - e, - "AlternateDataStreamNotFound", - ErrorCategory.ObjectNotFound, - path)); - } + WriteError(new ErrorRecord( + e, + "AlternateDataStreamNotFound", + ErrorCategory.ObjectNotFound, + path)); } } } @@ -8622,7 +8620,20 @@ internal static List GetStreams(string path) SafeFindHandle handle = NativeMethods.FindFirstStreamW( path, NativeMethods.StreamInfoLevels.FindStreamInfoStandard, findStreamData, 0); - if (handle.IsInvalid) throw new Win32Exception(); + if (handle.IsInvalid) + { + // Except for a test for handle.IsInvalid, this must be immediately after a P/Invoke call. + int error = Marshal.GetLastWin32Error(); + // Directories don't normally have alternate streams, so this is not an exceptional state. + // If a directory has no alternate data streams, FindFirstStreamW returns ERROR_HANDLE_EOF. + if (error == NativeMethods.ERROR_HANDLE_EOF) + { + return alternateStreams; + } + // Filesystems other than NTFS generally don't support alternate streams, so we still + // must be prepared to throw the error. It's usually ERROR_INVALID_PARAMETER in that case. + throw new Win32Exception(error); + } try { From ef27072be634768bd06d62a7cc55e36024fbd6e0 Mon Sep 17 00:00:00 2001 From: Kyle H Date: Fri, 18 Sep 2020 13:40:44 -0500 Subject: [PATCH 02/33] Adding tests for positive and negative stream finding --- .../Get-Item.Tests.ps1 | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 index 86b831ba8d0..f3af8ef27fc 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 @@ -112,16 +112,33 @@ Describe "Get-Item" -Tags "CI" { return } $altStreamPath = "$TESTDRIVE/altStream.txt" + $altStreamDirectory = "$TESTDRIVE/altstreamdir" $stringData = "test data" $streamName = "test" + $absentStreamName = "noExist" $item = New-Item -type file $altStreamPath Set-Content -Path $altStreamPath -Stream $streamName -Value $stringData + $diritem = New-Item -type directory $altStreamDirectory + #Set-Content -Path $altStreamDirectory -Stream $streamName -Value $stringData + cmd.exe /c echo ${stringData} > "${altStreamDirectory}:${streamName}" } - It "Should find an alternate stream if present" -Skip:$skipNotWindows { + It "Should find an alternate stream on a file if present" -Skip:$skipNotWindows { $result = Get-Item $altStreamPath -Stream $streamName $result.Length | Should -Be ($stringData.Length + [Environment]::NewLine.Length) $result.Stream | Should -Be $streamName } + It "Should error if it cannot find alternate stream on a file if not present" -Skip:$skipNotWindows { + { Get-Item $altStreamPath -Stream $absentStreamName -ErrorAction Stop } | Should -Throw -ErrorId "AlternateDataStreamNotFound,Microsoft.PowerShell.Commands.GetItemCommand" + } + It "Should find an alternate stream on a directory if present" -Skip:$skipNotWindows { + $result = Get-Item $altStreamDirectory -Stream $streamName + # cmd's echo appends another NewLine to the string it echoes, so we end up with 2 newlines. + $result.Length | Should -Be ($stringData.Length + (2 * [Environment]::NewLine.Length) ) + $result.Stream | Should -Be $streamName + } + It "Should not find an alternate stream on a directory if not present" -Skip:$skipNotWindows { + { Get-Item $altStreamDirectory -Stream $absentStreamName -ErrorAction Stop } | Should -Throw -ErrorId "AlternateDataStreamNotFound,Microsoft.PowerShell.Commands.GetItemCommand" + } } Context "Registry Provider" { From 188674c1e805f93c1b7310d4d981c5f785cc2f16 Mon Sep 17 00:00:00 2001 From: Kyle H Date: Sun, 20 Sep 2020 02:34:54 -0500 Subject: [PATCH 03/33] Address @iSazanov's comments, and add a necessary test --- .../Get-Item.Tests.ps1 | 39 +++++++++++-------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 index f3af8ef27fc..7d5e03479a7 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 @@ -112,33 +112,38 @@ Describe "Get-Item" -Tags "CI" { return } $altStreamPath = "$TESTDRIVE/altStream.txt" - $altStreamDirectory = "$TESTDRIVE/altstreamdir" + $altStreamDirectory = "$TESTDRIVE/altstreamdir" + $noAltStreamDirectory = "$TESTDRIVE/noaltstreamdir" $stringData = "test data" $streamName = "test" - $absentStreamName = "noExist" + $absentStreamName = "noExist" $item = New-Item -type file $altStreamPath Set-Content -Path $altStreamPath -Stream $streamName -Value $stringData - $diritem = New-Item -type directory $altStreamDirectory - #Set-Content -Path $altStreamDirectory -Stream $streamName -Value $stringData - cmd.exe /c echo ${stringData} > "${altStreamDirectory}:${streamName}" + $altstreamdiritem = New-Item -type directory $altStreamDirectory + cmd.exe /c echo ${stringData} > "${altStreamDirectory}:${streamName}" + $noaltstreamdiritem = New-Item -type directory $noAltStreamDirectory } It "Should find an alternate stream on a file if present" -Skip:$skipNotWindows { $result = Get-Item $altStreamPath -Stream $streamName $result.Length | Should -Be ($stringData.Length + [Environment]::NewLine.Length) $result.Stream | Should -Be $streamName } - It "Should error if it cannot find alternate stream on a file if not present" -Skip:$skipNotWindows { - { Get-Item $altStreamPath -Stream $absentStreamName -ErrorAction Stop } | Should -Throw -ErrorId "AlternateDataStreamNotFound,Microsoft.PowerShell.Commands.GetItemCommand" - } - It "Should find an alternate stream on a directory if present" -Skip:$skipNotWindows { - $result = Get-Item $altStreamDirectory -Stream $streamName - # cmd's echo appends another NewLine to the string it echoes, so we end up with 2 newlines. - $result.Length | Should -Be ($stringData.Length + (2 * [Environment]::NewLine.Length) ) - $result.Stream | Should -Be $streamName - } - It "Should not find an alternate stream on a directory if not present" -Skip:$skipNotWindows { - { Get-Item $altStreamDirectory -Stream $absentStreamName -ErrorAction Stop } | Should -Throw -ErrorId "AlternateDataStreamNotFound,Microsoft.PowerShell.Commands.GetItemCommand" - } + It "Should error if it cannot find alternate stream on a file if not present" -Skip:$skipNotWindows { + { Get-Item $altStreamPath -Stream $absentStreamName -ErrorAction Stop } | Should -Throw -ErrorId "AlternateDataStreamNotFound,Microsoft.PowerShell.Commands.GetItemCommand" + } + It "Should find an alternate stream on a directory if present" -Skip:$skipNotWindows { + $result = Get-Item $altStreamDirectory -Stream $streamName + # cmd's echo appends another NewLine to the string it echoes, so we end up with 2 newlines. + $result.Length | Should -Be ($stringData.Length + (2 * [Environment]::NewLine.Length) ) + $result.Stream | Should -Be $streamName + } + It "Should not find an alternate stream on a directory if not present" -Skip:$skipNotWindows { + { Get-Item $altStreamDirectory -Stream $absentStreamName -ErrorAction Stop } | Should -Throw -ErrorId "AlternateDataStreamNotFound,Microsoft.PowerShell.Commands.GetItemCommand" + } + It "Should find zero alt streams and not fail on a directory if no alt streams are present" -Skip:$skipNotWindows { + { $result = Get-Item $noAltStreamDirectory -Stream * -ErrorAction Stop + $result.Length | Should -Be (0) } | Should -Not -Throw + } } Context "Registry Provider" { From d3bcf45ce0f9921144a42e0000291ddcf55c2aa2 Mon Sep 17 00:00:00 2001 From: Kyle H Date: Sun, 20 Sep 2020 20:00:41 -0500 Subject: [PATCH 04/33] Address iSasanova's comments --- .../namespaces/FileSystemProvider.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/System.Management.Automation/namespaces/FileSystemProvider.cs b/src/System.Management.Automation/namespaces/FileSystemProvider.cs index 9a321a6fd1b..80b2665a7c6 100644 --- a/src/System.Management.Automation/namespaces/FileSystemProvider.cs +++ b/src/System.Management.Automation/namespaces/FileSystemProvider.cs @@ -8622,14 +8622,15 @@ internal static List GetStreams(string path) findStreamData, 0); if (handle.IsInvalid) { - // Except for a test for handle.IsInvalid, this must be immediately after a P/Invoke call. int error = Marshal.GetLastWin32Error(); + // Directories don't normally have alternate streams, so this is not an exceptional state. // If a directory has no alternate data streams, FindFirstStreamW returns ERROR_HANDLE_EOF. if (error == NativeMethods.ERROR_HANDLE_EOF) { return alternateStreams; } + // Filesystems other than NTFS generally don't support alternate streams, so we still // must be prepared to throw the error. It's usually ERROR_INVALID_PARAMETER in that case. throw new Win32Exception(error); From 8be94a1550d7fa3944d498b5ab6cd42a68738a37 Mon Sep 17 00:00:00 2001 From: Kyle H Date: Sun, 20 Sep 2020 20:01:29 -0500 Subject: [PATCH 05/33] Make the description of a test more precise --- .../Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 index 7d5e03479a7..3814edef57d 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 @@ -140,7 +140,7 @@ Describe "Get-Item" -Tags "CI" { It "Should not find an alternate stream on a directory if not present" -Skip:$skipNotWindows { { Get-Item $altStreamDirectory -Stream $absentStreamName -ErrorAction Stop } | Should -Throw -ErrorId "AlternateDataStreamNotFound,Microsoft.PowerShell.Commands.GetItemCommand" } - It "Should find zero alt streams and not fail on a directory if no alt streams are present" -Skip:$skipNotWindows { + It "Should find zero alt streams and not fail on a directory with a wildcard stream name if no alt streams are present" -Skip:$skipNotWindows { { $result = Get-Item $noAltStreamDirectory -Stream * -ErrorAction Stop $result.Length | Should -Be (0) } | Should -Not -Throw } From 698dd007757b901fb6d38b59c500f6649edc52c1 Mon Sep 17 00:00:00 2001 From: Kyle H Date: Tue, 22 Sep 2020 17:45:41 -0500 Subject: [PATCH 06/33] Update test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 Co-authored-by: Ilya --- .../Microsoft.PowerShell.Management/Get-Item.Tests.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 index 3814edef57d..d3c0567acbf 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 @@ -141,8 +141,8 @@ Describe "Get-Item" -Tags "CI" { { Get-Item $altStreamDirectory -Stream $absentStreamName -ErrorAction Stop } | Should -Throw -ErrorId "AlternateDataStreamNotFound,Microsoft.PowerShell.Commands.GetItemCommand" } It "Should find zero alt streams and not fail on a directory with a wildcard stream name if no alt streams are present" -Skip:$skipNotWindows { - { $result = Get-Item $noAltStreamDirectory -Stream * -ErrorAction Stop - $result.Length | Should -Be (0) } | Should -Not -Throw + $result = Get-Item $noAltStreamDirectory -Stream * -ErrorAction Stop + $result.Length | Should -Be 0 } } From 62c52843dcf6beecb348fef9d7bac4302a7bcce4 Mon Sep 17 00:00:00 2001 From: Kyle H Date: Wed, 30 Sep 2020 18:11:32 -0500 Subject: [PATCH 07/33] Doing the rest of the work for alternate data streams --- .../namespaces/FileSystemProvider.cs | 33 ++++++++++++++----- .../Add-Content.Tests.ps1 | 8 +++++ .../Clear-Content.Tests.ps1 | 8 +++++ .../Set-Content.Tests.ps1 | 27 +++++++++++++++ 4 files changed, 67 insertions(+), 9 deletions(-) diff --git a/src/System.Management.Automation/namespaces/FileSystemProvider.cs b/src/System.Management.Automation/namespaces/FileSystemProvider.cs index 80b2665a7c6..9bfabd0c6cf 100644 --- a/src/System.Management.Automation/namespaces/FileSystemProvider.cs +++ b/src/System.Management.Automation/namespaces/FileSystemProvider.cs @@ -6664,7 +6664,11 @@ public IContentReader GetContentReader(string path) try { - if (Directory.Exists(path)) + if (Directory.Exists(path) +#if !UNIX + && string.IsNullOrEmpty(streamName) +#endif + ) { string errMsg = StringUtil.Format(SessionStateStrings.GetContainerContentException, path); ErrorRecord error = new ErrorRecord(new InvalidOperationException(errMsg), "GetContainerContentException", ErrorCategory.InvalidOperation, null); @@ -6819,7 +6823,11 @@ public IContentWriter GetContentWriter(string path) try { - if (Directory.Exists(path)) + if (Directory.Exists(path) +#if !UNIX + && string.IsNullOrEmpty(streamName) +#endif + ) { string errMsg = StringUtil.Format(SessionStateStrings.WriteContainerContentException, path); ErrorRecord error = new ErrorRecord(new InvalidOperationException(errMsg), "WriteContainerContentException", ErrorCategory.InvalidOperation, null); @@ -6897,13 +6905,6 @@ public void ClearContent(string path) path = NormalizePath(path); - if (Directory.Exists(path)) - { - string errorMsg = StringUtil.Format(SessionStateStrings.ClearDirectoryContent, path); - WriteError(new ErrorRecord(new NotSupportedException(errorMsg), "ClearDirectoryContent", ErrorCategory.InvalidOperation, path)); - return; - } - try { #if !UNIX @@ -6955,6 +6956,20 @@ public void ClearContent(string path) clearStream = false; } +#endif + // This block is after we determine if a stream is being cleared because directories + // can have data streams that are not child items. They just don't have unnamed data streams. + if (Directory.Exists(path) +#if !UNIX + && !clearStream +#endif + ) + { + string errorMsg = StringUtil.Format(SessionStateStrings.ClearDirectoryContent, path); + WriteError(new ErrorRecord(new NotSupportedException(errorMsg), "ClearDirectoryContent", ErrorCategory.InvalidOperation, path)); + return; + } +#if !UNIX if (clearStream) { FileStream fileStream = null; diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Add-Content.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Add-Content.Tests.ps1 index d4bd23a6fee..c7252cc49c5 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Add-Content.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Add-Content.Tests.ps1 @@ -5,6 +5,9 @@ Describe "Add-Content cmdlet tests" -Tags "CI" { BeforeAll { $file1 = "file1.txt" Setup -File "$file1" + $directory1 = "addcontent" + Setup -Directory "$directory1" + $streamContent = "ShouldWork" } Context "Add-Content should actually add content" { @@ -47,6 +50,11 @@ Describe "Add-Content cmdlet tests" -Tags "CI" { { Add-Content -Path . -Value "WriteContainerContentException" -ErrorAction Stop } | Should -Throw -ErrorId "WriteContainerContentException,Microsoft.PowerShell.Commands.AddContentCommand" } + It "Should not throw an error on a directory datastream (on Windows)" -Skip:$skipNotWindows { + { Add-Content -Path TestDrive:\$directory1 -Stream Add-Content-Test-Stream -Value $streamContent -ErrorAction Stop } | Should -Not -Throw + Get-Content -Path TestDrive\$directory1 -Stream Add-Content-Test-Stream | Should -BeExactly $streamContent + } + #[BugId(BugDatabase.WindowsOutOfBandReleases, 906022)] It "should throw 'NotSupportedException' when you add-content to an unsupported provider" -Skip:($IsLinux -Or $IsMacOS) { { Add-Content -Path HKLM:\\software\\microsoft -Value "ShouldNotWorkBecausePathIsUnsupported" -ErrorAction Stop } | Should -Throw -ErrorId "NotSupported,Microsoft.PowerShell.Commands.AddContentCommand" diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 index e2ab56fc809..16ef40b0b74 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 @@ -51,6 +51,9 @@ Describe "Clear-Content cmdlet tests" -Tags "CI" { Setup -File "$file3" -Content $content2 $streamContent = "content for alternate stream" $streamName = "altStream1" + $dirName = "clearcontent" + Setup -Directory "$dirName" + Set-Content -Path "TestDrive:/$dirName" -Stream $streamName -Value $streamContent } Context "Clear-Content should actually clear content" { @@ -85,6 +88,11 @@ Describe "Clear-Content cmdlet tests" -Tags "CI" { Get-Content -Path "TestDrive:/$file3" | Should -BeExactly $content2 Get-Content -Path "TestDrive:/$file3" -Stream $streamName | Should -BeNullOrEmpty } + It "Should not error when targeting an existing stream on a directory." -Skip:$skipNotWindows { + { Set-Content -Path "TestDrive:/$dirName" -Stream $streamName -Value $streamContent } | Should -Not -Throw + Get-Content -Path "TestDrive:/$dirName" -Stream $streamName | Should -BeExactly $streamContent + { Clear-Content -Path TestDrive:\$dirName -Stream $streamName -ErrorAction Stop } | Should -Not -Throw + } It "the '-Stream' dynamic parameter is visible to get-command in the filesystem" -Skip:(!$IsWindows) { try { diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Set-Content.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Set-Content.Tests.ps1 index 6e8f8bde083..43d0a21cc6c 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Set-Content.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Set-Content.Tests.ps1 @@ -72,6 +72,33 @@ Describe "Set-Content cmdlet tests" -Tags "CI" { $result[1] | Should -BeExactly "world" } } + Context "Set-Content should work with alternate data streams on Windows" { + BeforeAll { + if ( $skipNotWindows ) + { + return + } + $altStreamPath = "$TESTDRIVE/altStream.txt" + $altStreamDirectory = "$TESTDRIVE/altstreamdir" + $stringData = "test data" + $streamName = "test" + $absentStreamName = "noExist" + $item = New-Item -type file $altStreamPath + $altstreamdiritem = New-Item -type directory $altStreamDirectory + } + It "Should create a new data stream on a file" -Skip:$skipNotWindows { + Set-Content -Path $altStreamPath -Stream $streamName -Value $stringData + } + It "Should create a new data stream on a file using colon syntax" -Skip:$skipNotWindows { + Set-Content -Path ${altStreamPath}:${streamName} -Value $stringData + } + It "Should create a new data stream on a directory" -Skip:$skipNotWindows { + { Set-Content -Path $altStreamDirectory -Stream $streamName -Value $stringData } | Should -Not -Throw + } + It "Should create a new data stream on a directory using colon syntax" -Skip:$skipNotWindows { + { Set-Content -Path ${altStreamDirectory}:${streamName} -Value $stringData } | Should -Not -Throw + } + } } Describe "Set-Content should work for PSDrive with UNC path as root" -Tags @('CI', 'RequireAdminOnWindows') { From 60c8d878ea2898dd0d6dbe6d264cb5ae0e9c9de6 Mon Sep 17 00:00:00 2001 From: Kyle H Date: Wed, 30 Sep 2020 21:12:20 -0500 Subject: [PATCH 08/33] Fix a missing colon --- .../Microsoft.PowerShell.Management/Add-Content.Tests.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Add-Content.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Add-Content.Tests.ps1 index c7252cc49c5..797d0a15651 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Add-Content.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Add-Content.Tests.ps1 @@ -51,8 +51,8 @@ Describe "Add-Content cmdlet tests" -Tags "CI" { } It "Should not throw an error on a directory datastream (on Windows)" -Skip:$skipNotWindows { - { Add-Content -Path TestDrive:\$directory1 -Stream Add-Content-Test-Stream -Value $streamContent -ErrorAction Stop } | Should -Not -Throw - Get-Content -Path TestDrive\$directory1 -Stream Add-Content-Test-Stream | Should -BeExactly $streamContent + Add-Content -Path TestDrive:\$directory1 -Stream Add-Content-Test-Stream -Value $streamContent -ErrorAction Stop + Get-Content -Path TestDrive:\$directory1 -Stream Add-Content-Test-Stream | Should -BeExactly $streamContent } #[BugId(BugDatabase.WindowsOutOfBandReleases, 906022)] From ccadb163d436fb56676a35926ca0c5909cb5a870 Mon Sep 17 00:00:00 2001 From: Kyle H Date: Wed, 30 Sep 2020 21:18:34 -0500 Subject: [PATCH 09/33] Apparently, $skipNotWindows is not defined in Add-Content.Tests.ps1. --- .../Microsoft.PowerShell.Management/Add-Content.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Add-Content.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Add-Content.Tests.ps1 index 797d0a15651..701734ccaef 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Add-Content.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Add-Content.Tests.ps1 @@ -50,7 +50,7 @@ Describe "Add-Content cmdlet tests" -Tags "CI" { { Add-Content -Path . -Value "WriteContainerContentException" -ErrorAction Stop } | Should -Throw -ErrorId "WriteContainerContentException,Microsoft.PowerShell.Commands.AddContentCommand" } - It "Should not throw an error on a directory datastream (on Windows)" -Skip:$skipNotWindows { + It "Should not throw an error on a directory datastream (on Windows)" -Skip:(-Not $IsWindows) { Add-Content -Path TestDrive:\$directory1 -Stream Add-Content-Test-Stream -Value $streamContent -ErrorAction Stop Get-Content -Path TestDrive:\$directory1 -Stream Add-Content-Test-Stream | Should -BeExactly $streamContent } From 4ae8e3854bdd4390f4587a131abad6e1712fb1e3 Mon Sep 17 00:00:00 2001 From: Kyle H Date: Wed, 30 Sep 2020 21:43:39 -0500 Subject: [PATCH 10/33] Fixing conditions for the stream tests in Set-Content.Tests.ps1 --- .../Set-Content.Tests.ps1 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Set-Content.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Set-Content.Tests.ps1 index 43d0a21cc6c..d69cdc177d3 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Set-Content.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Set-Content.Tests.ps1 @@ -74,7 +74,7 @@ Describe "Set-Content cmdlet tests" -Tags "CI" { } Context "Set-Content should work with alternate data streams on Windows" { BeforeAll { - if ( $skipNotWindows ) + if ( -Not $IsWindows ) { return } @@ -86,16 +86,16 @@ Describe "Set-Content cmdlet tests" -Tags "CI" { $item = New-Item -type file $altStreamPath $altstreamdiritem = New-Item -type directory $altStreamDirectory } - It "Should create a new data stream on a file" -Skip:$skipNotWindows { + It "Should create a new data stream on a file" -Skip:(-Not $IsWindows) { Set-Content -Path $altStreamPath -Stream $streamName -Value $stringData } - It "Should create a new data stream on a file using colon syntax" -Skip:$skipNotWindows { + It "Should create a new data stream on a file using colon syntax" -Skip:(-Not $IsWindows) { Set-Content -Path ${altStreamPath}:${streamName} -Value $stringData } - It "Should create a new data stream on a directory" -Skip:$skipNotWindows { + It "Should create a new data stream on a directory" -Skip:(-Not $IsWindows) { { Set-Content -Path $altStreamDirectory -Stream $streamName -Value $stringData } | Should -Not -Throw } - It "Should create a new data stream on a directory using colon syntax" -Skip:$skipNotWindows { + It "Should create a new data stream on a directory using colon syntax" -Skip:(-Not $IsWindows) { { Set-Content -Path ${altStreamDirectory}:${streamName} -Value $stringData } | Should -Not -Throw } } From 115ae16391fbb367579a467757c10f671a236b8b Mon Sep 17 00:00:00 2001 From: Kyle H Date: Wed, 30 Sep 2020 21:46:37 -0500 Subject: [PATCH 11/33] Fixing conditions for stream tests in Clear-Content.Tests.ps1 --- .../Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 index 16ef40b0b74..b026b350d5f 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 @@ -88,7 +88,7 @@ Describe "Clear-Content cmdlet tests" -Tags "CI" { Get-Content -Path "TestDrive:/$file3" | Should -BeExactly $content2 Get-Content -Path "TestDrive:/$file3" -Stream $streamName | Should -BeNullOrEmpty } - It "Should not error when targeting an existing stream on a directory." -Skip:$skipNotWindows { + It "Should not error when targeting an existing stream on a directory." -Skip:(!$IsWindows) { { Set-Content -Path "TestDrive:/$dirName" -Stream $streamName -Value $streamContent } | Should -Not -Throw Get-Content -Path "TestDrive:/$dirName" -Stream $streamName | Should -BeExactly $streamContent { Clear-Content -Path TestDrive:\$dirName -Stream $streamName -ErrorAction Stop } | Should -Not -Throw From 10957b6d11b422efcc44fdb311d8103470f90699 Mon Sep 17 00:00:00 2001 From: Kyle H Date: Wed, 30 Sep 2020 22:31:23 -0500 Subject: [PATCH 12/33] Guard a Windows-specific BeforeAll line --- .../Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 index b026b350d5f..149b965c9ef 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 @@ -53,7 +53,9 @@ Describe "Clear-Content cmdlet tests" -Tags "CI" { $streamName = "altStream1" $dirName = "clearcontent" Setup -Directory "$dirName" - Set-Content -Path "TestDrive:/$dirName" -Stream $streamName -Value $streamContent + if ($isWindows) { + Set-Content -Path "TestDrive:/$dirName" -Stream $streamName -Value $streamContent + } } Context "Clear-Content should actually clear content" { From 1b8d1db71f8b775917704c8472e396c0f32f953f Mon Sep 17 00:00:00 2001 From: Kyle H Date: Sat, 3 Oct 2020 20:33:12 -0500 Subject: [PATCH 13/33] Positive tests for alternate data stream behaviors --- .../Add-Content.Tests.ps1 | 17 +++-- .../Clear-Content.Tests.ps1 | 70 +++++++++++-------- .../Get-Content.Tests.ps1 | 38 +++++----- .../Get-Item.Tests.ps1 | 8 +-- .../Remove-Item.Tests.ps1 | 43 +++++++++++- .../Set-Content.Tests.ps1 | 10 ++- 6 files changed, 126 insertions(+), 60 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Add-Content.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Add-Content.Tests.ps1 index 701734ccaef..2bb66f664fc 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Add-Content.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Add-Content.Tests.ps1 @@ -5,8 +5,6 @@ Describe "Add-Content cmdlet tests" -Tags "CI" { BeforeAll { $file1 = "file1.txt" Setup -File "$file1" - $directory1 = "addcontent" - Setup -Directory "$directory1" $streamContent = "ShouldWork" } @@ -50,9 +48,18 @@ Describe "Add-Content cmdlet tests" -Tags "CI" { { Add-Content -Path . -Value "WriteContainerContentException" -ErrorAction Stop } | Should -Throw -ErrorId "WriteContainerContentException,Microsoft.PowerShell.Commands.AddContentCommand" } - It "Should not throw an error on a directory datastream (on Windows)" -Skip:(-Not $IsWindows) { - Add-Content -Path TestDrive:\$directory1 -Stream Add-Content-Test-Stream -Value $streamContent -ErrorAction Stop - Get-Content -Path TestDrive:\$directory1 -Stream Add-Content-Test-Stream | Should -BeExactly $streamContent + Context "Add-Content should work with alternate data streams on Windows" { + BeforeAll { + if (!$isWindows) { + return + } + $directory1 = "addcontent" + Setup -Directory "$directory1" + } + It "Should not throw an error on a directory datastream (on Windows)" -Skip:(-Not $IsWindows) { + Add-Content -Path TestDrive:\$directory1 -Stream Add-Content-Test-Stream -Value $streamContent -ErrorAction Stop + Get-Content -Path TestDrive:\$directory1 -Stream Add-Content-Test-Stream | Should -BeExactly $streamContent + } } #[BugId(BugDatabase.WindowsOutOfBandReleases, 906022)] diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 index 149b965c9ef..07687d6489a 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 @@ -80,40 +80,52 @@ Describe "Clear-Content cmdlet tests" -Tags "CI" { $cci.SupportsShouldProcess | Should -BeTrue } - It "Alternate streams should be cleared with clear-content" -Skip:(!$IsWindows) { - # make sure that the content is correct - # this is here rather than BeforeAll because only windows can write to an alternate stream - Set-Content -Path "TestDrive:/$file3" -Stream $streamName -Value $streamContent - Get-Content -Path "TestDrive:/$file3" | Should -BeExactly $content2 - Get-Content -Path "TestDrive:/$file3" -Stream $streamName | Should -BeExactly $streamContent - Clear-Content -Path "TestDrive:/$file3" -Stream $streamName - Get-Content -Path "TestDrive:/$file3" | Should -BeExactly $content2 - Get-Content -Path "TestDrive:/$file3" -Stream $streamName | Should -BeNullOrEmpty - } - It "Should not error when targeting an existing stream on a directory." -Skip:(!$IsWindows) { - { Set-Content -Path "TestDrive:/$dirName" -Stream $streamName -Value $streamContent } | Should -Not -Throw - Get-Content -Path "TestDrive:/$dirName" -Stream $streamName | Should -BeExactly $streamContent - { Clear-Content -Path TestDrive:\$dirName -Stream $streamName -ErrorAction Stop } | Should -Not -Throw - } - - It "the '-Stream' dynamic parameter is visible to get-command in the filesystem" -Skip:(!$IsWindows) { - try { - Push-Location -Path TestDrive: - (Get-Command Clear-Content -Stream foo).parameters.keys -eq "stream" | Should -Be "stream" + Context "Clear-Content should work with alternate data streams on Windows" { + BeforeAll { + if (!$IsWindows) + { + return + } + Set-Content -Path "TestDrive:/$file3" -Stream $streamName -Value $streamContent + Set-Content -Path "TestDrive:/$dirName" -Stream $streamName -Value $streamContent + } + It "Alternate streams should be cleared with Clear-Content" -Skip:(!$IsWindows) { + # Make sure the test is set up correctly. + Set-Content -Path "TestDrive:/$file3" -Stream $streamName -Value $streamContent + # Truncate the stream. + Clear-Content -Path "TestDrive:/$file3" -Stream $streamName -ErrorAction Stop + # The stream should exist, but should have 0 length. + $result = Get-Item -Path "TestDrive:/$file3" -Stream $streamName + $result | Should -Not -BeNullOrEmpty + $result.length | Should -Be 0 + } + It "Should not error when clearing an alternate stream on a directory" -Skip:(!$IsWindows) { + # Make sure the test is set up correctly. + Set-Content -Path "TestDrive:/$dirName" -Stream $streamName -Value $streamContent + # Truncate the stream. + Clear-Content -Path "TestDrive:/$dirName" -Stream $streamName -ErrorAction Stop + # The stream should exist, but should have 0 length. + $result = Get-Item -Path "TestDrive:/$dirName" -Stream $streamName + $result | Should -Not -BeNullOrEmpty + $result.length | Should -Be 0 } - finally { + It "the '-Stream' dynamic parameter is visible to get-command in the filesystem" -Skip:(!$IsWindows) { + try { + Push-Location -Path TestDrive: + (Get-Command Clear-Content -Stream foo).parameters.keys -eq "stream" | Should -Be "stream" + } + finally { + Pop-Location + } + } + It "the '-Stream' dynamic parameter should not be visible to get-command in the function provider" { + Push-Location -Path function: + { Get-Command Clear-Content -Stream $streamName } | + Should -Throw -ErrorId "NamedParameterNotFound,Microsoft.PowerShell.Commands.GetCommandCommand" Pop-Location } } - - It "the '-Stream' dynamic parameter should not be visible to get-command in the function provider" { - Push-Location -Path function: - { Get-Command Clear-Content -Stream $streamName } | - Should -Throw -ErrorId "NamedParameterNotFound,Microsoft.PowerShell.Commands.GetCommandCommand" - Pop-Location - } } - Context "Proper errors should be delivered when bad locations are specified" { It "should throw when targetting a directory." { { Clear-Content -Path . -ErrorAction Stop } | Should -Throw -ErrorId "ClearDirectoryContent" diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Content.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Content.Tests.ps1 index 6c50cee5aa8..5fdc904580d 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Content.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Content.Tests.ps1 @@ -221,25 +221,27 @@ Describe "Get-Content" -Tags "CI" { $expected = 'He', 'o,', '', 'Wor', "d${nl}He", 'o2,', '', 'Wor', "d2${nl}" for ($i = 0; $i -lt $result.Length ; $i++) { $result[$i] | Should -BeExactly $expected[$i]} } + + Context "Alternate Data Stream support on Windows" { + It "Should support NTFS streams using colon syntax" -Skip:(!$IsWindows) { + Set-Content "${testPath}:Stream" -Value "Foo" + { Test-Path "${testPath}:Stream" | Should -Throw -ErrorId "ItemExistsNotSupportedError,Microsoft.PowerShell.Commands,TestPathCommand" } + Get-Content "${testPath}:Stream" | Should -BeExactly "Foo" + Get-Content $testPath | Should -BeExactly $testString + } - It "Should support NTFS streams using colon syntax" -Skip:(!$IsWindows) { - Set-Content "${testPath}:Stream" -Value "Foo" - { Test-Path "${testPath}:Stream" | Should -Throw -ErrorId "ItemExistsNotSupportedError,Microsoft.PowerShell.Commands,TestPathCommand" } - Get-Content "${testPath}:Stream" | Should -BeExactly "Foo" - Get-Content $testPath | Should -BeExactly $testString - } - - It "Should support NTFS streams using -Stream" -Skip:(!$IsWindows) { - Set-Content -Path $testPath -Stream hello -Value World - Get-Content -Path $testPath | Should -BeExactly $testString - Get-Content -Path $testPath -Stream hello | Should -BeExactly "World" - $item = Get-Item -Path $testPath -Stream hello - $item | Should -BeOfType System.Management.Automation.Internal.AlternateStreamData - $item.Stream | Should -BeExactly "hello" - Clear-Content -Path $testPath -Stream hello - Get-Content -Path $testPath -Stream hello | Should -BeNullOrEmpty - Remove-Item -Path $testPath -Stream hello - { Get-Content -Path $testPath -Stream hello | Should -Throw -ErrorId "GetContentReaderFileNotFoundError,Microsoft.PowerShell.Commands.GetContentCommand" } + It "Should support NTFS streams using -Stream" -Skip:(!$IsWindows) { + Set-Content -Path $testPath -Stream hello -Value World + Get-Content -Path $testPath | Should -BeExactly $testString + Get-Content -Path $testPath -Stream hello | Should -BeExactly "World" + $item = Get-Item -Path $testPath -Stream hello + $item | Should -BeOfType System.Management.Automation.Internal.AlternateStreamData + $item.Stream | Should -BeExactly "hello" + Clear-Content -Path $testPath -Stream hello + Get-Content -Path $testPath -Stream hello | Should -BeNullOrEmpty + Remove-Item -Path $testPath -Stream hello + { Get-Content -Path $testPath -Stream hello -ErrorAction stop} | Should -Throw -ErrorId "GetContentReaderFileNotFoundError,Microsoft.PowerShell.Commands.GetContentCommand" + } } It "Should support colons in filename on Linux/Mac" -Skip:($IsWindows) { diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 index d3c0567acbf..b9da71166c9 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 @@ -117,11 +117,11 @@ Describe "Get-Item" -Tags "CI" { $stringData = "test data" $streamName = "test" $absentStreamName = "noExist" - $item = New-Item -type file $altStreamPath + New-Item -type file $altStreamPath Set-Content -Path $altStreamPath -Stream $streamName -Value $stringData - $altstreamdiritem = New-Item -type directory $altStreamDirectory + New-Item -type directory $altStreamDirectory cmd.exe /c echo ${stringData} > "${altStreamDirectory}:${streamName}" - $noaltstreamdiritem = New-Item -type directory $noAltStreamDirectory + New-Item -type directory $noAltStreamDirectory } It "Should find an alternate stream on a file if present" -Skip:$skipNotWindows { $result = Get-Item $altStreamPath -Stream $streamName @@ -138,7 +138,7 @@ Describe "Get-Item" -Tags "CI" { $result.Stream | Should -Be $streamName } It "Should not find an alternate stream on a directory if not present" -Skip:$skipNotWindows { - { Get-Item $altStreamDirectory -Stream $absentStreamName -ErrorAction Stop } | Should -Throw -ErrorId "AlternateDataStreamNotFound,Microsoft.PowerShell.Commands.GetItemCommand" + { Get-Item $noAltStreamDirectory -Stream $absentStreamName -ErrorAction Stop } | Should -Throw -ErrorId "AlternateDataStreamNotFound,Microsoft.PowerShell.Commands.GetItemCommand" } It "Should find zero alt streams and not fail on a directory with a wildcard stream name if no alt streams are present" -Skip:$skipNotWindows { $result = Get-Item $noAltStreamDirectory -Stream * -ErrorAction Stop diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Remove-Item.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Remove-Item.Tests.ps1 index 769a8a34003..471abc5bc3e 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Remove-Item.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Remove-Item.Tests.ps1 @@ -7,9 +7,7 @@ Describe "Remove-Item" -Tags "CI" { Context "File removal Tests" { BeforeEach { New-Item -Name $testfile -Path $testpath -ItemType "file" -Value "lorem ipsum" -Force - Test-Path $testfilepath | Should -BeTrue - } It "Should be able to be called on a regular file without error using the Path parameter" { @@ -138,4 +136,45 @@ Describe "Remove-Item" -Tags "CI" { Test-Path $testdirectory | Should -BeFalse } } + + Context "Alternate Data Streams should be supported on Windows" { + BeforeAll { + $fileName = "ADStest.txt" + $streamName = "teststream" + $dirName = "ADStestdir" + $fileContent =" This is file content." + $streamContent = "datastream content here" + $streamfile = Join-Path -Path $testpath -ChildPath $fileName + $streamdir = Join-Path -Path $testpath -ChildPath $dirName + + New-Item -Path $streamfile -ItemType "File" -force + Add-Content -Path $streamfile -Value $fileContent + Add-Content -Path $streamfile -Stream $streamName -Value $streamContent + New-Item -Path $streamdir -ItemType "Directory" -Force + Add-Content -Path $streamdir -Stream $streamName -Value $streamContent + } +# BeforeEach { +# Remove-Item $fileName +# Remove-Item $dirName -Recurse +# New-Item -Name $fileName -Path $testpath -ItemType "File" -force +# Add-Content -Name $fileName -Content $fileContent +# Add-Content -Name $fileName -Stream $streamName -Content $streamContent +# New-Item -Name $dirName -Path $testpath -ItemType "Directory" -Force +# Add-Content -Name $dirName -Stream $streamName -Content $streamContent +# } + It "Should completely remove a datastream from a file" { + # First, we verify that the stream exists. + Get-Item -Path $streamfile -Stream $streamName | Should -Not -BeNullOrEmpty + # Now, remove the stream and verify it's gone. + Remove-Item -Path $streamfile -Stream $streamName + Get-Item -Path $streamfile -Stream $streamName -ErrorAction SilentlyContinue | Should -BeNullOrEmpty + } + It "Should completely remove a datastream from a directory" { + # First, we verify that the stream exists. + Get-Item -Path $streamdir -Stream $streamName | Should -Not -BeNullOrEmpty + # Now, remove the stream and verify it's gone. + Remove-Item -Path $streamdir -Stream $streamName + Get-Item -Path $streamdir -Stream $streamname -ErrorAction SilentlyContinue | Should -BeNullOrEmpty + } + } } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Set-Content.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Set-Content.Tests.ps1 index d69cdc177d3..603d71617ac 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Set-Content.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Set-Content.Tests.ps1 @@ -79,7 +79,9 @@ Describe "Set-Content cmdlet tests" -Tags "CI" { return } $altStreamPath = "$TESTDRIVE/altStream.txt" + $altStreamPath2 = "$TESTDRIVE/altStream2.txt" $altStreamDirectory = "$TESTDRIVE/altstreamdir" + $altStreamDirectory2 = "$TESTDRIVE/altstream2dir" $stringData = "test data" $streamName = "test" $absentStreamName = "noExist" @@ -88,15 +90,19 @@ Describe "Set-Content cmdlet tests" -Tags "CI" { } It "Should create a new data stream on a file" -Skip:(-Not $IsWindows) { Set-Content -Path $altStreamPath -Stream $streamName -Value $stringData + Get-Content -Path $altStreamPath -Stream $streamName | Should -BeExactly $stringData } It "Should create a new data stream on a file using colon syntax" -Skip:(-Not $IsWindows) { - Set-Content -Path ${altStreamPath}:${streamName} -Value $stringData + Set-Content -Path ${altStreamPath2}:${streamName} -Value $stringData + Get-Content -Path ${altStreamPath2} -Stream $streamName | Should -BeExactly $stringData } It "Should create a new data stream on a directory" -Skip:(-Not $IsWindows) { { Set-Content -Path $altStreamDirectory -Stream $streamName -Value $stringData } | Should -Not -Throw + Get-Content -Path $altStreamDirectory -Stream $streamName | Should -BeExactly $stringData } It "Should create a new data stream on a directory using colon syntax" -Skip:(-Not $IsWindows) { - { Set-Content -Path ${altStreamDirectory}:${streamName} -Value $stringData } | Should -Not -Throw + Set-Content -Path ${altStreamDirectory2}:${streamName} -Value $stringData + Get-Content -Path ${altStreamDirectory2} -Stream ${streamName} | Should -BeExactly $stringData } } } From 2ecca2854534d5bfe7b77f32a88cc925c42b281c Mon Sep 17 00:00:00 2001 From: Kyle H Date: Sat, 3 Oct 2020 20:59:04 -0500 Subject: [PATCH 14/33] Fixes to non-Windows test runs. --- .../Remove-Item.Tests.ps1 | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Remove-Item.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Remove-Item.Tests.ps1 index 471abc5bc3e..da5d141f71b 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Remove-Item.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Remove-Item.Tests.ps1 @@ -139,6 +139,9 @@ Describe "Remove-Item" -Tags "CI" { Context "Alternate Data Streams should be supported on Windows" { BeforeAll { + if (!$IsWindows) { + return + } $fileName = "ADStest.txt" $streamName = "teststream" $dirName = "ADStestdir" @@ -153,23 +156,14 @@ Describe "Remove-Item" -Tags "CI" { New-Item -Path $streamdir -ItemType "Directory" -Force Add-Content -Path $streamdir -Stream $streamName -Value $streamContent } -# BeforeEach { -# Remove-Item $fileName -# Remove-Item $dirName -Recurse -# New-Item -Name $fileName -Path $testpath -ItemType "File" -force -# Add-Content -Name $fileName -Content $fileContent -# Add-Content -Name $fileName -Stream $streamName -Content $streamContent -# New-Item -Name $dirName -Path $testpath -ItemType "Directory" -Force -# Add-Content -Name $dirName -Stream $streamName -Content $streamContent -# } - It "Should completely remove a datastream from a file" { + It "Should completely remove a datastream from a file" -Skip:(!$IsWindows) { # First, we verify that the stream exists. Get-Item -Path $streamfile -Stream $streamName | Should -Not -BeNullOrEmpty # Now, remove the stream and verify it's gone. Remove-Item -Path $streamfile -Stream $streamName Get-Item -Path $streamfile -Stream $streamName -ErrorAction SilentlyContinue | Should -BeNullOrEmpty } - It "Should completely remove a datastream from a directory" { + It "Should completely remove a datastream from a directory" -Skip:(!$IsWindows) { # First, we verify that the stream exists. Get-Item -Path $streamdir -Stream $streamName | Should -Not -BeNullOrEmpty # Now, remove the stream and verify it's gone. From 6bce44acbe35464475e5e2b009ecdae88cd26878 Mon Sep 17 00:00:00 2001 From: Kyle H Date: Mon, 5 Oct 2020 02:04:15 -0500 Subject: [PATCH 15/33] Update test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 Co-authored-by: Ilya --- .../Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 index 07687d6489a..e59b14c0a73 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 @@ -89,7 +89,7 @@ Describe "Clear-Content cmdlet tests" -Tags "CI" { Set-Content -Path "TestDrive:/$file3" -Stream $streamName -Value $streamContent Set-Content -Path "TestDrive:/$dirName" -Stream $streamName -Value $streamContent } - It "Alternate streams should be cleared with Clear-Content" -Skip:(!$IsWindows) { + It "Alternate streams should be cleared with Clear-Content on a file" -Skip:(!$IsWindows) { # Make sure the test is set up correctly. Set-Content -Path "TestDrive:/$file3" -Stream $streamName -Value $streamContent # Truncate the stream. From deae9550c71561040dfa44bb4be0d9ee63cc4efa Mon Sep 17 00:00:00 2001 From: Kyle H Date: Mon, 5 Oct 2020 02:04:55 -0500 Subject: [PATCH 16/33] Update test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 Co-authored-by: Ilya --- .../Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 index e59b14c0a73..8f94beb7e46 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 @@ -99,7 +99,7 @@ Describe "Clear-Content cmdlet tests" -Tags "CI" { $result | Should -Not -BeNullOrEmpty $result.length | Should -Be 0 } - It "Should not error when clearing an alternate stream on a directory" -Skip:(!$IsWindows) { + It "Alternate streams should be cleared with Clear-Content on a directory" -Skip:(!$IsWindows) { # Make sure the test is set up correctly. Set-Content -Path "TestDrive:/$dirName" -Stream $streamName -Value $streamContent # Truncate the stream. From 250d500a694225c652f2bdce1789a1de08bccd8c Mon Sep 17 00:00:00 2001 From: Kyle H Date: Mon, 5 Oct 2020 05:18:30 -0500 Subject: [PATCH 17/33] Friendlier error message when a filesystem doesn't support ADS --- .../namespaces/FileSystemProvider.cs | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/System.Management.Automation/namespaces/FileSystemProvider.cs b/src/System.Management.Automation/namespaces/FileSystemProvider.cs index 9bfabd0c6cf..ee7e9b90641 100644 --- a/src/System.Management.Automation/namespaces/FileSystemProvider.cs +++ b/src/System.Management.Automation/namespaces/FileSystemProvider.cs @@ -6957,8 +6957,14 @@ public void ClearContent(string path) } #endif - // This block is after we determine if a stream is being cleared because directories - // can have data streams that are not child items. They just don't have unnamed data streams. + // On Windows, determine if our argument is a directory only after we determine if + // we're being asked to work with an alternate data stream, because directories can have + // alternate data streams on them that are not child items. These alternate data streams + // must be treated as data streams, even if they're attached to directories. However, + // if asked to work with a directory without a data stream specified, write a non-terminating + // error instead of clearing all child items of the directory. (On non-Windows, alternate + // data streams don't exist, so in that environment always write the error when addressing + // a directory.) if (Directory.Exists(path) #if !UNIX && !clearStream @@ -8646,8 +8652,15 @@ internal static List GetStreams(string path) return alternateStreams; } - // Filesystems other than NTFS generally don't support alternate streams, so we still - // must be prepared to throw the error. It's usually ERROR_INVALID_PARAMETER in that case. + // Filesystems other than NTFS generally don't support alternate streams, and the system + // sets ERROR_INVALID_PARAMETER in that case. + if (error == NativeMethods.ERROR_INVALID_PARAMETER) + { + throw new NotSupportedException("This filesystem does not support alternate data streams."); + } + + // An unexpected error was returned, that we don't know how to interpret. The most helpful + // thing we can do at this point is simply throw the raw Win32 exception. throw new Win32Exception(error); } @@ -8784,6 +8797,7 @@ internal static void SetZoneOfOrigin(string path, SecurityZone securityZone) internal static class NativeMethods { internal const int ERROR_HANDLE_EOF = 38; + internal const int ERROR_INVALID_PARAMETER = 87; internal enum StreamInfoLevels { FindStreamInfoStandard = 0 } From 3ed7aadcb185c1ccf81023d8b123c77ae94c43d4 Mon Sep 17 00:00:00 2001 From: Kyle H Date: Mon, 5 Oct 2020 06:35:44 -0500 Subject: [PATCH 18/33] Updated tests for alternate data streams --- .../Add-Content.Tests.ps1 | 17 ++++++++++++----- .../Clear-Content.Tests.ps1 | 2 ++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Add-Content.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Add-Content.Tests.ps1 index 2bb66f664fc..e601971ba87 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Add-Content.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Add-Content.Tests.ps1 @@ -53,12 +53,19 @@ Describe "Add-Content cmdlet tests" -Tags "CI" { if (!$isWindows) { return } - $directory1 = "addcontent" - Setup -Directory "$directory1" + $ADSTestDir = "addcontentadstest" + $ADSTestFile = "addcontentads.txt" + $streamContent = "This is a test stream." + Setup -Directory "$ADSTestDir" + Setup -File "$ADSTestFile" } - It "Should not throw an error on a directory datastream (on Windows)" -Skip:(-Not $IsWindows) { - Add-Content -Path TestDrive:\$directory1 -Stream Add-Content-Test-Stream -Value $streamContent -ErrorAction Stop - Get-Content -Path TestDrive:\$directory1 -Stream Add-Content-Test-Stream | Should -BeExactly $streamContent + It "Should add an alternate data stream on a directory" -Skip:(!$IsWindows) { + Add-Content -Path TestDrive:\$ADSTestDir -Stream Add-Content-Test-Stream -Value $streamContent -ErrorAction Stop + Get-Content -Path TestDrive:\$ADSTestDir -Stream Add-Content-Test-Stream | Should -BeExactly $streamContent + } + It "Should add an alternate data stream on a file" -Skip:(!$IsWindows) { + Add-Content -Path TestDrive:\$ADSTestFile -Stream Add-Content-Test-Stream -Value $streamContent -ErrorAction Stop + Get-Content -Path TestDrive:\$ADSTestFile -Stream Add-Content-Test-Stream | Should -BeExactly $streamContent } } diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 index 8f94beb7e46..e3ccb0f53f6 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 @@ -92,6 +92,7 @@ Describe "Clear-Content cmdlet tests" -Tags "CI" { It "Alternate streams should be cleared with Clear-Content on a file" -Skip:(!$IsWindows) { # Make sure the test is set up correctly. Set-Content -Path "TestDrive:/$file3" -Stream $streamName -Value $streamContent + Get-Content -Path "TestDrive:/$file3" -Stream $streamName | Should -BeExactly $streamContent # Truncate the stream. Clear-Content -Path "TestDrive:/$file3" -Stream $streamName -ErrorAction Stop # The stream should exist, but should have 0 length. @@ -103,6 +104,7 @@ Describe "Clear-Content cmdlet tests" -Tags "CI" { # Make sure the test is set up correctly. Set-Content -Path "TestDrive:/$dirName" -Stream $streamName -Value $streamContent # Truncate the stream. + Get-Content -Path "TestDrive:/$dirName" -Stream $streamName | Should -BeExactly $streamContent Clear-Content -Path "TestDrive:/$dirName" -Stream $streamName -ErrorAction Stop # The stream should exist, but should have 0 length. $result = Get-Item -Path "TestDrive:/$dirName" -Stream $streamName From 7dbb7c47abe1a2fd7e573788ab9ba8bb2f0ca14f Mon Sep 17 00:00:00 2001 From: Kyle H Date: Mon, 5 Oct 2020 07:04:31 -0500 Subject: [PATCH 19/33] Added some comments to explain why directories are sometimes allowed in (Get|Set|Add)-Content --- .../namespaces/FileSystemProvider.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/System.Management.Automation/namespaces/FileSystemProvider.cs b/src/System.Management.Automation/namespaces/FileSystemProvider.cs index ee7e9b90641..37552ce6d37 100644 --- a/src/System.Management.Automation/namespaces/FileSystemProvider.cs +++ b/src/System.Management.Automation/namespaces/FileSystemProvider.cs @@ -6664,6 +6664,9 @@ public IContentReader GetContentReader(string path) try { + // Get-Content will write a non-terminating error if the target is a directory. + // On Windows, the streamName must be null or empty for it to write the error. Otherwise, the + // alternate data stream is not a directory, even if it's set on a directory. if (Directory.Exists(path) #if !UNIX && string.IsNullOrEmpty(streamName) @@ -6823,6 +6826,9 @@ public IContentWriter GetContentWriter(string path) try { + // Add-Content and Set-Content will write a non-terminating error if the target is a directory. + // On Windows, the streamName must be null or empty for it to write the error. Otherwise, the + // alternate data stream is not a directory, even if it's set on a directory. if (Directory.Exists(path) #if !UNIX && string.IsNullOrEmpty(streamName) From 402630ac4c600f071ed6680ed59e39347b1d36ca Mon Sep 17 00:00:00 2001 From: Kyle H Date: Mon, 5 Oct 2020 11:59:51 -0500 Subject: [PATCH 20/33] Update test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 Co-authored-by: Ilya --- .../Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 index b9da71166c9..7d0fb9b30e6 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 @@ -117,7 +117,7 @@ Describe "Get-Item" -Tags "CI" { $stringData = "test data" $streamName = "test" $absentStreamName = "noExist" - New-Item -type file $altStreamPath + $null = New-Item -type file $altStreamPath Set-Content -Path $altStreamPath -Stream $streamName -Value $stringData New-Item -type directory $altStreamDirectory cmd.exe /c echo ${stringData} > "${altStreamDirectory}:${streamName}" From 37a9e11cc337a849c648cfcf31bab74cd5969167 Mon Sep 17 00:00:00 2001 From: Kyle H Date: Mon, 5 Oct 2020 12:00:05 -0500 Subject: [PATCH 21/33] Update test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 Co-authored-by: Ilya --- .../Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 index 7d0fb9b30e6..b49fcee8e3e 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 @@ -119,7 +119,7 @@ Describe "Get-Item" -Tags "CI" { $absentStreamName = "noExist" $null = New-Item -type file $altStreamPath Set-Content -Path $altStreamPath -Stream $streamName -Value $stringData - New-Item -type directory $altStreamDirectory + $null = New-Item -type directory $altStreamDirectory cmd.exe /c echo ${stringData} > "${altStreamDirectory}:${streamName}" New-Item -type directory $noAltStreamDirectory } From 49f5ff1cee07fde607fb5cacf67774e655691a2e Mon Sep 17 00:00:00 2001 From: Kyle H Date: Mon, 5 Oct 2020 12:02:39 -0500 Subject: [PATCH 22/33] Update test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 Co-authored-by: Ilya --- .../Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 index b49fcee8e3e..6596cdc7323 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 @@ -121,7 +121,7 @@ Describe "Get-Item" -Tags "CI" { Set-Content -Path $altStreamPath -Stream $streamName -Value $stringData $null = New-Item -type directory $altStreamDirectory cmd.exe /c echo ${stringData} > "${altStreamDirectory}:${streamName}" - New-Item -type directory $noAltStreamDirectory + $null = New-Item -type directory $noAltStreamDirectory } It "Should find an alternate stream on a file if present" -Skip:$skipNotWindows { $result = Get-Item $altStreamPath -Stream $streamName From 5929b7a8123255c3555a1870eb933384548cfcf8 Mon Sep 17 00:00:00 2001 From: Kyle H Date: Mon, 5 Oct 2020 12:11:14 -0500 Subject: [PATCH 23/33] Make a confusing check be an explicit type check --- .../Clear-Content.Tests.ps1 | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 index e3ccb0f53f6..f3ac9525bce 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 @@ -54,6 +54,7 @@ Describe "Clear-Content cmdlet tests" -Tags "CI" { $dirName = "clearcontent" Setup -Directory "$dirName" if ($isWindows) { + Set-Content -Path "TestDrive:/$file3" -Stream $streamName -Value $streamContent Set-Content -Path "TestDrive:/$dirName" -Stream $streamName -Value $streamContent } } @@ -81,14 +82,6 @@ Describe "Clear-Content cmdlet tests" -Tags "CI" { } Context "Clear-Content should work with alternate data streams on Windows" { - BeforeAll { - if (!$IsWindows) - { - return - } - Set-Content -Path "TestDrive:/$file3" -Stream $streamName -Value $streamContent - Set-Content -Path "TestDrive:/$dirName" -Stream $streamName -Value $streamContent - } It "Alternate streams should be cleared with Clear-Content on a file" -Skip:(!$IsWindows) { # Make sure the test is set up correctly. Set-Content -Path "TestDrive:/$file3" -Stream $streamName -Value $streamContent @@ -108,7 +101,7 @@ Describe "Clear-Content cmdlet tests" -Tags "CI" { Clear-Content -Path "TestDrive:/$dirName" -Stream $streamName -ErrorAction Stop # The stream should exist, but should have 0 length. $result = Get-Item -Path "TestDrive:/$dirName" -Stream $streamName - $result | Should -Not -BeNullOrEmpty + $result | Should -BeOfType System.Management.Automation.Internal.AlternateStreamData $result.length | Should -Be 0 } It "the '-Stream' dynamic parameter is visible to get-command in the filesystem" -Skip:(!$IsWindows) { From 451d4b46f95611a5506ff2182f08e36230d190ea Mon Sep 17 00:00:00 2001 From: Kyle H Date: Tue, 6 Oct 2020 00:14:51 -0500 Subject: [PATCH 24/33] Removing redundant test setup --- .../Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 index f3ac9525bce..cccc074a614 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 @@ -53,10 +53,6 @@ Describe "Clear-Content cmdlet tests" -Tags "CI" { $streamName = "altStream1" $dirName = "clearcontent" Setup -Directory "$dirName" - if ($isWindows) { - Set-Content -Path "TestDrive:/$file3" -Stream $streamName -Value $streamContent - Set-Content -Path "TestDrive:/$dirName" -Stream $streamName -Value $streamContent - } } Context "Clear-Content should actually clear content" { From a665fb82f70b6c8aba385ada0d6d1eea9a5ca037 Mon Sep 17 00:00:00 2001 From: Kyle H Date: Tue, 6 Oct 2020 15:21:54 -0500 Subject: [PATCH 25/33] Change a test to test for specific type Co-authored-by: Ilya --- .../Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 index cccc074a614..766ac0af1e2 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 @@ -86,7 +86,7 @@ Describe "Clear-Content cmdlet tests" -Tags "CI" { Clear-Content -Path "TestDrive:/$file3" -Stream $streamName -ErrorAction Stop # The stream should exist, but should have 0 length. $result = Get-Item -Path "TestDrive:/$file3" -Stream $streamName - $result | Should -Not -BeNullOrEmpty + $result | Should -BeOfType System.Management.Automation.Internal.AlternateStreamData $result.length | Should -Be 0 } It "Alternate streams should be cleared with Clear-Content on a directory" -Skip:(!$IsWindows) { From 646139c4c3e550c1e7c1fb97142c2eceae63497f Mon Sep 17 00:00:00 2001 From: Kyle H Date: Thu, 8 Oct 2020 15:16:46 -0500 Subject: [PATCH 26/33] Update test/powershell/Modules/Microsoft.PowerShell.Management/Remove-Item.Tests.ps1 prevent unwanted console output. Co-authored-by: Ilya --- .../Microsoft.PowerShell.Management/Remove-Item.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Remove-Item.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Remove-Item.Tests.ps1 index da5d141f71b..e1d7ca86ad5 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Remove-Item.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Remove-Item.Tests.ps1 @@ -150,7 +150,7 @@ Describe "Remove-Item" -Tags "CI" { $streamfile = Join-Path -Path $testpath -ChildPath $fileName $streamdir = Join-Path -Path $testpath -ChildPath $dirName - New-Item -Path $streamfile -ItemType "File" -force + $null = New-Item -Path $streamfile -ItemType "File" -force Add-Content -Path $streamfile -Value $fileContent Add-Content -Path $streamfile -Stream $streamName -Value $streamContent New-Item -Path $streamdir -ItemType "Directory" -Force From 124f23f0cc6cc1c0e6df0441f9dc34d6515926ac Mon Sep 17 00:00:00 2001 From: Kyle H Date: Thu, 8 Oct 2020 15:17:19 -0500 Subject: [PATCH 27/33] Update test/powershell/Modules/Microsoft.PowerShell.Management/Remove-Item.Tests.ps1 Prevent unwanted console output. Co-authored-by: Ilya --- .../Microsoft.PowerShell.Management/Remove-Item.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Remove-Item.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Remove-Item.Tests.ps1 index e1d7ca86ad5..90651071e43 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Remove-Item.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Remove-Item.Tests.ps1 @@ -153,7 +153,7 @@ Describe "Remove-Item" -Tags "CI" { $null = New-Item -Path $streamfile -ItemType "File" -force Add-Content -Path $streamfile -Value $fileContent Add-Content -Path $streamfile -Stream $streamName -Value $streamContent - New-Item -Path $streamdir -ItemType "Directory" -Force + $null = New-Item -Path $streamdir -ItemType "Directory" -Force Add-Content -Path $streamdir -Stream $streamName -Value $streamContent } It "Should completely remove a datastream from a file" -Skip:(!$IsWindows) { From fe0e8a8271457c6f3074eddc36b6a8cae9ac4155 Mon Sep 17 00:00:00 2001 From: Kyle H Date: Thu, 8 Oct 2020 15:18:13 -0500 Subject: [PATCH 28/33] Update test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 Additional positive type checking on the result. Co-authored-by: Ilya --- .../Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 index 6596cdc7323..dd8db3bf027 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 @@ -142,6 +142,7 @@ Describe "Get-Item" -Tags "CI" { } It "Should find zero alt streams and not fail on a directory with a wildcard stream name if no alt streams are present" -Skip:$skipNotWindows { $result = Get-Item $noAltStreamDirectory -Stream * -ErrorAction Stop + $result | Should -BeOfType System.Management.Automation.Internal.AlternateStreamData $result.Length | Should -Be 0 } } From ad8edeaf147fdf927530232ac22aab9bab917c07 Mon Sep 17 00:00:00 2001 From: Kyle H Date: Thu, 8 Oct 2020 15:19:08 -0500 Subject: [PATCH 29/33] Update test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 Be precise in our key comparisons. Co-authored-by: Ilya --- .../Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 index 766ac0af1e2..23aeb8d3247 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 @@ -103,7 +103,7 @@ Describe "Clear-Content cmdlet tests" -Tags "CI" { It "the '-Stream' dynamic parameter is visible to get-command in the filesystem" -Skip:(!$IsWindows) { try { Push-Location -Path TestDrive: - (Get-Command Clear-Content -Stream foo).parameters.keys -eq "stream" | Should -Be "stream" + (Get-Command Clear-Content -Stream foo).parameters.keys -eq "Stream" | Should -BeExactly "Stream" } finally { Pop-Location From 5a518a96d73559acfad338fa49b91aa7abe267e5 Mon Sep 17 00:00:00 2001 From: Kyle H Date: Sat, 10 Oct 2020 00:53:56 -0500 Subject: [PATCH 30/33] Fix a test that an accepted suggestion broke --- .../Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 index dd8db3bf027..a6a3a419137 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Item.Tests.ps1 @@ -142,8 +142,7 @@ Describe "Get-Item" -Tags "CI" { } It "Should find zero alt streams and not fail on a directory with a wildcard stream name if no alt streams are present" -Skip:$skipNotWindows { $result = Get-Item $noAltStreamDirectory -Stream * -ErrorAction Stop - $result | Should -BeOfType System.Management.Automation.Internal.AlternateStreamData - $result.Length | Should -Be 0 + $result | Should -Be $null } } From 0c45cadf8eeda13448cc8e0c7a10d6098520823f Mon Sep 17 00:00:00 2001 From: Kyle H Date: Sat, 10 Oct 2020 01:16:36 -0500 Subject: [PATCH 31/33] Migrate the error message to FileSystemProviderStrings.resx. --- .../namespaces/FileSystemProvider.cs | 3 ++- .../resources/FileSystemProviderStrings.resx | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/System.Management.Automation/namespaces/FileSystemProvider.cs b/src/System.Management.Automation/namespaces/FileSystemProvider.cs index 37552ce6d37..c5dfda351bc 100644 --- a/src/System.Management.Automation/namespaces/FileSystemProvider.cs +++ b/src/System.Management.Automation/namespaces/FileSystemProvider.cs @@ -8662,7 +8662,8 @@ internal static List GetStreams(string path) // sets ERROR_INVALID_PARAMETER in that case. if (error == NativeMethods.ERROR_INVALID_PARAMETER) { - throw new NotSupportedException("This filesystem does not support alternate data streams."); + throw new NotSupportedException( + string.Format(FileSystemProviderStrings.AlternateDataStreamNotSupported, path)); } // An unexpected error was returned, that we don't know how to interpret. The most helpful diff --git a/src/System.Management.Automation/resources/FileSystemProviderStrings.resx b/src/System.Management.Automation/resources/FileSystemProviderStrings.resx index 1b4d1159e59..474f5b53cd0 100644 --- a/src/System.Management.Automation/resources/FileSystemProviderStrings.resx +++ b/src/System.Management.Automation/resources/FileSystemProviderStrings.resx @@ -345,4 +345,7 @@ Skip already-visited directory {0}. + + Alternate data streams are not supported for the path {0}. + From cc845c3293dd62e5c171f455a987455487de6445 Mon Sep 17 00:00:00 2001 From: Kyle H Date: Sun, 11 Oct 2020 00:32:50 -0500 Subject: [PATCH 32/33] Finishing the last batch of changes requested by @iSazonov --- .../namespaces/FileSystemProvider.cs | 8 ------ .../resources/FileSystemProviderStrings.resx | 3 --- .../Clear-Content.Tests.ps1 | 27 ++++++++++++------- .../Set-Content.Tests.ps1 | 2 +- 4 files changed, 18 insertions(+), 22 deletions(-) diff --git a/src/System.Management.Automation/namespaces/FileSystemProvider.cs b/src/System.Management.Automation/namespaces/FileSystemProvider.cs index c5dfda351bc..02f925affbd 100644 --- a/src/System.Management.Automation/namespaces/FileSystemProvider.cs +++ b/src/System.Management.Automation/namespaces/FileSystemProvider.cs @@ -8658,14 +8658,6 @@ internal static List GetStreams(string path) return alternateStreams; } - // Filesystems other than NTFS generally don't support alternate streams, and the system - // sets ERROR_INVALID_PARAMETER in that case. - if (error == NativeMethods.ERROR_INVALID_PARAMETER) - { - throw new NotSupportedException( - string.Format(FileSystemProviderStrings.AlternateDataStreamNotSupported, path)); - } - // An unexpected error was returned, that we don't know how to interpret. The most helpful // thing we can do at this point is simply throw the raw Win32 exception. throw new Win32Exception(error); diff --git a/src/System.Management.Automation/resources/FileSystemProviderStrings.resx b/src/System.Management.Automation/resources/FileSystemProviderStrings.resx index 474f5b53cd0..1b4d1159e59 100644 --- a/src/System.Management.Automation/resources/FileSystemProviderStrings.resx +++ b/src/System.Management.Automation/resources/FileSystemProviderStrings.resx @@ -345,7 +345,4 @@ Skip already-visited directory {0}. - - Alternate data streams are not supported for the path {0}. - diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 index 23aeb8d3247..ff9d0c8f39c 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Clear-Content.Tests.ps1 @@ -79,27 +79,28 @@ Describe "Clear-Content cmdlet tests" -Tags "CI" { Context "Clear-Content should work with alternate data streams on Windows" { It "Alternate streams should be cleared with Clear-Content on a file" -Skip:(!$IsWindows) { - # Make sure the test is set up correctly. + Set-Content -Path "TestDrive:/$file3" -Stream $streamName -Value $streamContent Get-Content -Path "TestDrive:/$file3" -Stream $streamName | Should -BeExactly $streamContent - # Truncate the stream. + Clear-Content -Path "TestDrive:/$file3" -Stream $streamName -ErrorAction Stop - # The stream should exist, but should have 0 length. + $result = Get-Item -Path "TestDrive:/$file3" -Stream $streamName $result | Should -BeOfType System.Management.Automation.Internal.AlternateStreamData $result.length | Should -Be 0 } + It "Alternate streams should be cleared with Clear-Content on a directory" -Skip:(!$IsWindows) { - # Make sure the test is set up correctly. Set-Content -Path "TestDrive:/$dirName" -Stream $streamName -Value $streamContent - # Truncate the stream. + Get-Content -Path "TestDrive:/$dirName" -Stream $streamName | Should -BeExactly $streamContent Clear-Content -Path "TestDrive:/$dirName" -Stream $streamName -ErrorAction Stop - # The stream should exist, but should have 0 length. + $result = Get-Item -Path "TestDrive:/$dirName" -Stream $streamName $result | Should -BeOfType System.Management.Automation.Internal.AlternateStreamData $result.length | Should -Be 0 } + It "the '-Stream' dynamic parameter is visible to get-command in the filesystem" -Skip:(!$IsWindows) { try { Push-Location -Path TestDrive: @@ -109,14 +110,20 @@ Describe "Clear-Content cmdlet tests" -Tags "CI" { Pop-Location } } - It "the '-Stream' dynamic parameter should not be visible to get-command in the function provider" { + + It "the '-Stream' dynamic parameter should not be visible to get-command in the function provider" -Skip:(!$IsWindows) { + try { Push-Location -Path function: - { Get-Command Clear-Content -Stream $streamName } | - Should -Throw -ErrorId "NamedParameterNotFound,Microsoft.PowerShell.Commands.GetCommandCommand" - Pop-Location + { Get-Command Clear-Content -Stream $streamName } | + Should -Throw -ErrorId "NamedParameterNotFound,Microsoft.PowerShell.Commands.GetCommandCommand" + } + finally { + Pop-Location + } } } } + Context "Proper errors should be delivered when bad locations are specified" { It "should throw when targetting a directory." { { Clear-Content -Path . -ErrorAction Stop } | Should -Throw -ErrorId "ClearDirectoryContent" diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Set-Content.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Set-Content.Tests.ps1 index 603d71617ac..fefd73412df 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Set-Content.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Set-Content.Tests.ps1 @@ -97,7 +97,7 @@ Describe "Set-Content cmdlet tests" -Tags "CI" { Get-Content -Path ${altStreamPath2} -Stream $streamName | Should -BeExactly $stringData } It "Should create a new data stream on a directory" -Skip:(-Not $IsWindows) { - { Set-Content -Path $altStreamDirectory -Stream $streamName -Value $stringData } | Should -Not -Throw + Set-Content -Path $altStreamDirectory -Stream $streamName -Value $stringData Get-Content -Path $altStreamDirectory -Stream $streamName | Should -BeExactly $stringData } It "Should create a new data stream on a directory using colon syntax" -Skip:(-Not $IsWindows) { From 745105a28984e545290e1f437754631d090c4904 Mon Sep 17 00:00:00 2001 From: Kyle H Date: Fri, 16 Oct 2020 21:51:54 -0500 Subject: [PATCH 33/33] fixing test file to have fewer comments --- .../Microsoft.PowerShell.Management/Remove-Item.Tests.ps1 | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Remove-Item.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Remove-Item.Tests.ps1 index 90651071e43..3e8ccb8fa91 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Remove-Item.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Remove-Item.Tests.ps1 @@ -157,16 +157,12 @@ Describe "Remove-Item" -Tags "CI" { Add-Content -Path $streamdir -Stream $streamName -Value $streamContent } It "Should completely remove a datastream from a file" -Skip:(!$IsWindows) { - # First, we verify that the stream exists. Get-Item -Path $streamfile -Stream $streamName | Should -Not -BeNullOrEmpty - # Now, remove the stream and verify it's gone. Remove-Item -Path $streamfile -Stream $streamName Get-Item -Path $streamfile -Stream $streamName -ErrorAction SilentlyContinue | Should -BeNullOrEmpty } It "Should completely remove a datastream from a directory" -Skip:(!$IsWindows) { - # First, we verify that the stream exists. Get-Item -Path $streamdir -Stream $streamName | Should -Not -BeNullOrEmpty - # Now, remove the stream and verify it's gone. Remove-Item -Path $streamdir -Stream $streamName Get-Item -Path $streamdir -Stream $streamname -ErrorAction SilentlyContinue | Should -BeNullOrEmpty }