Enhance Remove-Item to work with OneDrive (Second) (#15260)

This commit is contained in:
Ilya
2021-04-27 12:31:12 -07:00
committed by GitHub
parent 1df4236e6c
commit 08e731398c
5 changed files with 275 additions and 146 deletions
@@ -2699,7 +2699,7 @@ namespace Microsoft.PowerShell.Commands
try
{
System.IO.DirectoryInfo di = new(providerPath);
if (di != null && (di.Attributes & System.IO.FileAttributes.ReparsePoint) != 0)
if (di != null && InternalSymbolicLinkLinkCodeMethods.IsReparsePointLikeSymlink(di))
{
shouldRecurse = false;
treatAsFile = true;
@@ -1863,7 +1863,7 @@ namespace System.Management.Automation
if (ExperimentalFeature.IsEnabled("PSAnsiRendering"))
{
PSStyle psstyle = PSStyle.Instance;
PSStyle psstyle = PSStyle.Instance;
switch (formatStyle)
{
case FormatStyle.Reset:
@@ -2100,6 +2100,13 @@ namespace System.Management.Automation.Internal
internal static bool ThrowExdevErrorOnMoveDirectory;
// To emulate OneDrive behavior we use the hard-coded symlink.
// If OneDriveTestRecuseOn is false then the symlink works as regular symlink.
// If OneDriveTestRecuseOn is true then we resurce into the symlink as OneDrive should work.
internal static bool OneDriveTestOn;
internal static bool OneDriveTestRecurseOn;
internal static string OneDriveTestSymlinkName = "link-Beta";
/// <summary>This member is used for internal test purposes.</summary>
public static void SetTestHook(string property, object value)
{
@@ -1890,9 +1890,14 @@ namespace Microsoft.PowerShell.Commands
}
bool hidden = false;
bool checkReparsePoint = true;
if (!Force)
{
hidden = (recursiveDirectory.Attributes & FileAttributes.Hidden) != 0;
// We've already taken the expense of initializing the Attributes property here,
// so we can use that to avoid needing to call IsReparsePointLikeSymlink() later.
checkReparsePoint = (recursiveDirectory.Attributes & FileAttributes.ReparsePoint) != 0;
}
// if "Hidden" is explicitly specified anywhere in the attribute filter, then override
@@ -1906,7 +1911,7 @@ namespace Microsoft.PowerShell.Commands
// c) it is not a reparse point with a target (not OneDrive or an AppX link).
if (tracker == null)
{
if (InternalSymbolicLinkLinkCodeMethods.IsReparsePointWithTarget(recursiveDirectory))
if (checkReparsePoint && InternalSymbolicLinkLinkCodeMethods.IsReparsePointLikeSymlink(recursiveDirectory))
{
continue;
}
@@ -2058,7 +2063,7 @@ namespace Microsoft.PowerShell.Commands
public static string NameString(PSObject instance)
{
return instance?.BaseObject is FileSystemInfo fileInfo
? InternalSymbolicLinkLinkCodeMethods.IsReparsePointWithTarget(fileInfo)
? InternalSymbolicLinkLinkCodeMethods.IsReparsePointLikeSymlink(fileInfo)
? $"{fileInfo.Name} -> {InternalSymbolicLinkLinkCodeMethods.GetTarget(instance)}"
: fileInfo.Name
: string.Empty;
@@ -3098,22 +3103,31 @@ namespace Microsoft.PowerShell.Commands
continueRemoval = ShouldProcess(directory.FullName, action);
}
if (directory.Attributes.HasFlag(FileAttributes.ReparsePoint))
if (InternalSymbolicLinkLinkCodeMethods.IsReparsePointLikeSymlink(directory))
{
void WriteErrorHelper(Exception exception)
{
WriteError(new ErrorRecord(exception, errorId: "DeleteSymbolicLinkFailed", ErrorCategory.WriteError, directory));
}
try
{
// TODO:
// Different symlinks seem to vary by behavior.
// In particular, OneDrive symlinks won't remove without recurse,
// but the .NET API here does not allow us to distinguish them.
// We may need to revisit using p/Invokes here to get the right behavior
directory.Delete();
if (InternalTestHooks.OneDriveTestOn)
{
WriteErrorHelper(new IOException());
return;
}
else
{
// Name surrogates should just be detached.
directory.Delete();
}
}
catch (Exception e)
{
string error = StringUtil.Format(FileSystemProviderStrings.CannotRemoveItem, directory.FullName, e.Message);
var exception = new IOException(error, e);
WriteError(new ErrorRecord(exception, errorId: "DeleteSymbolicLinkFailed", ErrorCategory.WriteError, directory));
WriteErrorHelper(exception);
}
return;
@@ -8024,7 +8038,7 @@ namespace Microsoft.PowerShell.Commands
}
// SetLastError is false as the use of this API doesn't not require GetLastError() to be called
[DllImport(PinvokeDllNames.FindFirstFileDllName, EntryPoint = "FindFirstFileExW", SetLastError = false, CharSet = CharSet.Unicode)]
[DllImport(PinvokeDllNames.FindFirstFileDllName, EntryPoint = "FindFirstFileExW", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern SafeFindHandle FindFirstFileEx(string lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, ref WIN32_FIND_DATA lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, IntPtr lpSearchFilter, int dwAdditionalFlags);
internal enum FINDEX_INFO_LEVELS : uint
@@ -8215,28 +8229,50 @@ namespace Microsoft.PowerShell.Commands
return fileInfo.Attributes.HasFlag(System.IO.FileAttributes.ReparsePoint);
}
internal static bool IsReparsePointWithTarget(FileSystemInfo fileInfo)
internal static bool IsReparsePointLikeSymlink(FileSystemInfo fileInfo)
{
if (!IsReparsePoint(fileInfo))
#if UNIX
// Reparse point on Unix is a symlink.
return IsReparsePoint(fileInfo);
#else
if (InternalTestHooks.OneDriveTestOn && fileInfo.Name == InternalTestHooks.OneDriveTestSymlinkName)
{
return false;
return !InternalTestHooks.OneDriveTestRecurseOn;
}
#if !UNIX
// It is a reparse point and we should check some reparse point tags.
var data = new WIN32_FIND_DATA();
using (var handle = FindFirstFileEx(fileInfo.FullName, FINDEX_INFO_LEVELS.FindExInfoBasic, ref data, FINDEX_SEARCH_OPS.FindExSearchNameMatch, IntPtr.Zero, 0))
WIN32_FIND_DATA data = default;
string fullPath = Path.TrimEndingDirectorySeparator(fileInfo.FullName);
using (var handle = FindFirstFileEx(fullPath, FINDEX_INFO_LEVELS.FindExInfoBasic, ref data, FINDEX_SEARCH_OPS.FindExSearchNameMatch, IntPtr.Zero, 0))
{
if (handle.IsInvalid)
{
// Our handle could be invalidated by something else touching the filesystem,
// so ensure we deal with that possibility here
int lastError = Marshal.GetLastWin32Error();
throw new Win32Exception(lastError);
}
// We already have the file attribute information from our Win32 call,
// so no need to take the expense of the FileInfo.FileAttributes call
const int FILE_ATTRIBUTE_REPARSE_POINT = 0x0400;
if ((data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0)
{
// Not a reparse point.
return false;
}
// The name surrogate bit 0x20000000 is defined in https://docs.microsoft.com/windows/win32/fileio/reparse-point-tags
// Name surrogates (0x20000000) are reparse points that point to other named entities local to the filesystem
// (like symlinks and mount points).
// In the case of OneDrive, they are not name surrogates and would be safe to recurse into.
if (!handle.IsInvalid && (data.dwReserved0 & 0x20000000) == 0 && (data.dwReserved0 != IO_REPARSE_TAG_APPEXECLINK))
if ((data.dwReserved0 & 0x20000000) == 0 && (data.dwReserved0 != IO_REPARSE_TAG_APPEXECLINK))
{
return false;
}
}
#endif
return true;
#endif
}
internal static bool WinIsHardLink(FileSystemInfo fileInfo)
@@ -570,7 +570,7 @@ Describe "Hard link and symbolic link tests" -Tags "CI", "RequireAdminOnWindows"
$omegaFile1 = Join-Path $omegaDir "OmegaFile1"
$omegaFile2 = Join-Path $omegaDir "OmegaFile2"
$betaDir = Join-Path $alphaDir "sub-Beta"
$betaLink = Join-Path $alphaDir "link-Beta"
$betaLink = Join-Path $alphaDir "link-Beta" # Don't change! The name is hard-coded in PowerShell for OneDrive tests.
$betaFile1 = Join-Path $betaDir "BetaFile1.txt"
$betaFile2 = Join-Path $betaDir "BetaFile2.txt"
$betaFile3 = Join-Path $betaDir "BetaFile3.txt"
@@ -623,6 +623,31 @@ Describe "Hard link and symbolic link tests" -Tags "CI", "RequireAdminOnWindows"
$ci = Get-ChildItem $alphaLink -Recurse -Name
$ci.Count | Should -BeExactly 7 # returns 10 - unexpectly recurce in link-alpha\link-Beta. See https://github.com/PowerShell/PowerShell/issues/11614
}
It "Get-ChildItem will recurse into emulated OneDrive directory" -Skip:(-not $IsWindows) {
# The test depends on the files created in previous test:
#New-Item -ItemType SymbolicLink -Path $alphaLink -Value $alphaDir
#New-Item -ItemType SymbolicLink -Path $betaLink -Value $betaDir
[System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('OneDriveTestOn', $true)
[System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('OneDriveTestRecurseOn', $false)
try
{
# '$betaDir' is a symlink - we don't follow symlinks
# This emulates PowerShell 6.2 and below behavior.
$ci = Get-ChildItem -Path $alphaDir -Recurse
$ci.Count | Should -BeExactly 7
# Now we follow the symlink like on OneDrive.
[System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('OneDriveTestRecurseOn', $true)
$ci = Get-ChildItem -Path $alphaDir -Recurse
$ci.Count | Should -BeExactly 10
}
finally
{
[System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('OneDriveTestRecurseOn', $false)
[System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('OneDriveTestOn', $false)
}
}
It "Get-ChildItem will recurse into symlinks given -FollowSymlink, avoiding link loops" {
New-Item -ItemType Directory -Path $gammaDir
New-Item -ItemType SymbolicLink -Path $uponeLink -Value $betaDir
@@ -744,6 +769,42 @@ Describe "Hard link and symbolic link tests" -Tags "CI", "RequireAdminOnWindows"
$childB.Count | Should -BeExactly $childA.Count
$childB.Name | Should -BeExactly $childA.Name
}
It "Remove-Item will recurse into emulated OneDrive directory" -Skip:(-not $IsWindows) {
$alphaDir = Join-Path $TestDrive "sub-alpha2"
$alphaLink = Join-Path $TestDrive "link-alpha2"
$alphaFile1 = Join-Path $alphaDir "AlphaFile1.txt"
$betaDir = Join-Path $alphaDir "sub-Beta"
$betaLink = Join-Path $alphaDir "link-Beta"
$betaFile1 = Join-Path $betaDir "BetaFile1.txt"
New-Item -ItemType Directory -Path $alphaDir > $null
New-Item -ItemType File -Path $alphaFile1 > $null
New-Item -ItemType Directory -Path $betaDir > $null
New-Item -ItemType File -Path $betaFile1 > $null
New-Item -ItemType SymbolicLink -Path $alphaLink -Value $alphaDir > $null
New-Item -ItemType SymbolicLink -Path $betaLink -Value $betaDir > $null
[System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('OneDriveTestOn', $true)
[System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('OneDriveTestRecurseOn', $false)
try
{
# With the test hook turned on we don't remove '$betaDir' symlink.
# This emulates PowerShell 7.1 and below behavior.
{ Remove-Item -Path $betaLink -Recurse -ErrorAction Stop } | Should -Throw -ErrorId "DeleteSymbolicLinkFailed,Microsoft.PowerShell.Commands.RemoveItemCommand"
# Now we emulate OneDrive and follow the symlink like on OneDrive.
[System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('OneDriveTestRecurseOn', $true)
Remove-Item -Path $betaLink -Recurse
Test-Path -Path $betaLink | Should -BeFalse
}
finally
{
[System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('OneDriveTestRecurseOn', $false)
[System.Management.Automation.Internal.InternalTestHooks]::SetTestHook('OneDriveTestOn', $false)
}
}
}
}
@@ -1,170 +1,195 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
Describe "Remove-Item" -Tags "CI" {
$testpath = $TestDrive
$testfile = "testfile.txt"
$testfilepath = Join-Path -Path $testpath -ChildPath $testfile
BeforeAll {
$testpath = $TestDrive
$testfile = "testfile.txt"
$testfilepath = Join-Path -Path $testpath -ChildPath $testfile
}
Context "File removal Tests" {
BeforeEach {
New-Item -Name $testfile -Path $testpath -ItemType "file" -Value "lorem ipsum" -Force
Test-Path $testfilepath | Should -BeTrue
}
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" {
{ Remove-Item -Path $testfilepath } | Should -Not -Throw
It "Should be able to be called on a regular file without error using the Path parameter" {
{ Remove-Item -Path $testfilepath } | Should -Not -Throw
Test-Path $testfilepath | Should -BeFalse
}
Test-Path $testfilepath | Should -BeFalse
}
It "Should be able to be called on a file without the Path parameter" {
{ Remove-Item $testfilepath } | Should -Not -Throw
It "Should be able to be called on a file without the Path parameter" {
{ Remove-Item $testfilepath } | Should -Not -Throw
Test-Path $testfilepath | Should -BeFalse
}
Test-Path $testfilepath | Should -BeFalse
}
It "Should be able to call the rm alias" {
{ rm $testfilepath } | Should -Not -Throw
It "Should be able to call the rm alias" {
{ rm $testfilepath } | Should -Not -Throw
Test-Path $testfilepath | Should -BeFalse
}
Test-Path $testfilepath | Should -BeFalse
}
It "Should be able to call the del alias" {
{ del $testfilepath } | Should -Not -Throw
It "Should be able to call the del alias" {
{ del $testfilepath } | Should -Not -Throw
Test-Path $testfilepath | Should -BeFalse
}
Test-Path $testfilepath | Should -BeFalse
}
It "Should be able to call the erase alias" {
{ erase $testfilepath } | Should -Not -Throw
It "Should be able to call the erase alias" {
{ erase $testfilepath } | Should -Not -Throw
Test-Path $testfilepath | Should -BeFalse
}
Test-Path $testfilepath | Should -BeFalse
}
It "Should be able to call the ri alias" {
{ ri $testfilepath } | Should -Not -Throw
It "Should be able to call the ri alias" {
{ ri $testfilepath } | Should -Not -Throw
Test-Path $testfilepath | Should -BeFalse
}
Test-Path $testfilepath | Should -BeFalse
}
It "Should not be able to remove a read-only document without using the force switch" {
# Set to read only
Set-ItemProperty -Path $testfilepath -Name IsReadOnly -Value $true
It "Should not be able to remove a read-only document without using the force switch" {
# Set to read only
Set-ItemProperty -Path $testfilepath -Name IsReadOnly -Value $true
# attempt to remove the file
{ Remove-Item $testfilepath -ErrorAction SilentlyContinue } | Should -Not -Throw
# attempt to remove the file
{ Remove-Item $testfilepath -ErrorAction SilentlyContinue } | Should -Not -Throw
# validate
Test-Path $testfilepath | Should -BeTrue
# validate
Test-Path $testfilepath | Should -BeTrue
# remove using the -force switch on the readonly object
Remove-Item $testfilepath -Force
# remove using the -force switch on the readonly object
Remove-Item $testfilepath -Force
# Validate
Test-Path $testfilepath | Should -BeFalse
}
# Validate
Test-Path $testfilepath | Should -BeFalse
}
It "Should be able to remove all files matching a regular expression with the include parameter" {
# Create multiple files with specific string
New-Item -Name file1.txt -Path $testpath -ItemType "file" -Value "lorem ipsum"
New-Item -Name file2.txt -Path $testpath -ItemType "file" -Value "lorem ipsum"
New-Item -Name file3.txt -Path $testpath -ItemType "file" -Value "lorem ipsum"
# Create a single file that does not match that string - already done in BeforeEach
It "Should be able to remove all files matching a regular expression with the include parameter" {
# Create multiple files with specific string
New-Item -Name file1.txt -Path $testpath -ItemType "file" -Value "lorem ipsum"
New-Item -Name file2.txt -Path $testpath -ItemType "file" -Value "lorem ipsum"
New-Item -Name file3.txt -Path $testpath -ItemType "file" -Value "lorem ipsum"
# Create a single file that does not match that string - already done in BeforeEach
# Delete the specific string
Remove-Item (Join-Path -Path $testpath -ChildPath "*") -Include file*.txt
# validate that the string under test was deleted, and the nonmatching strings still exist
Test-Path (Join-Path -Path $testpath -ChildPath file1.txt) | Should -BeFalse
Test-Path (Join-Path -Path $testpath -ChildPath file2.txt) | Should -BeFalse
Test-Path (Join-Path -Path $testpath -ChildPath file3.txt) | Should -BeFalse
Test-Path $testfilepath | Should -BeTrue
# Delete the specific string
Remove-Item (Join-Path -Path $testpath -ChildPath "*") -Include file*.txt
# validate that the string under test was deleted, and the nonmatching strings still exist
Test-Path (Join-Path -Path $testpath -ChildPath file1.txt) | Should -BeFalse
Test-Path (Join-Path -Path $testpath -ChildPath file2.txt) | Should -BeFalse
Test-Path (Join-Path -Path $testpath -ChildPath file3.txt) | Should -BeFalse
Test-Path $testfilepath | Should -BeTrue
# Delete the non-matching strings
Remove-Item $testfilepath
# Delete the non-matching strings
Remove-Item $testfilepath
Test-Path $testfilepath | Should -BeFalse
}
Test-Path $testfilepath | Should -BeFalse
}
It "Should be able to not remove any files matching a regular expression with the exclude parameter" {
# Create multiple files with specific string
New-Item -Name file1.wav -Path $testpath -ItemType "file" -Value "lorem ipsum"
New-Item -Name file2.wav -Path $testpath -ItemType "file" -Value "lorem ipsum"
It "Should be able to not remove any files matching a regular expression with the exclude parameter" {
# Create multiple files with specific string
New-Item -Name file1.wav -Path $testpath -ItemType "file" -Value "lorem ipsum"
New-Item -Name file2.wav -Path $testpath -ItemType "file" -Value "lorem ipsum"
# Create a single file that does not match that string
New-Item -Name file1.txt -Path $testpath -ItemType "file" -Value "lorem ipsum"
# Create a single file that does not match that string
New-Item -Name file1.txt -Path $testpath -ItemType "file" -Value "lorem ipsum"
# Delete the specific string
Remove-Item (Join-Path -Path $testpath -ChildPath "file*") -Exclude *.wav -Include *.txt
# Delete the specific string
Remove-Item (Join-Path -Path $testpath -ChildPath "file*") -Exclude *.wav -Include *.txt
# validate that the string under test was deleted, and the nonmatching strings still exist
Test-Path (Join-Path -Path $testpath -ChildPath file1.wav) | Should -BeTrue
Test-Path (Join-Path -Path $testpath -ChildPath file2.wav) | Should -BeTrue
Test-Path (Join-Path -Path $testpath -ChildPath file1.txt) | Should -BeFalse
# validate that the string under test was deleted, and the nonmatching strings still exist
Test-Path (Join-Path -Path $testpath -ChildPath file1.wav) | Should -BeTrue
Test-Path (Join-Path -Path $testpath -ChildPath file2.wav) | Should -BeTrue
Test-Path (Join-Path -Path $testpath -ChildPath file1.txt) | Should -BeFalse
# Delete the non-matching strings
Remove-Item (Join-Path -Path $testpath -ChildPath file1.wav)
Remove-Item (Join-Path -Path $testpath -ChildPath file2.wav)
# Delete the non-matching strings
Remove-Item (Join-Path -Path $testpath -ChildPath file1.wav)
Remove-Item (Join-Path -Path $testpath -ChildPath file2.wav)
Test-Path (Join-Path -Path $testpath -ChildPath file1.wav) | Should -BeFalse
Test-Path (Join-Path -Path $testpath -ChildPath file2.wav) | Should -BeFalse
}
Test-Path (Join-Path -Path $testpath -ChildPath file1.wav) | Should -BeFalse
Test-Path (Join-Path -Path $testpath -ChildPath file2.wav) | Should -BeFalse
}
}
Context "Directory Removal Tests" {
$testdirectory = Join-Path -Path $testpath -ChildPath testdir
$testsubdirectory = Join-Path -Path $testdirectory -ChildPath subd
BeforeEach {
New-Item -Name "testdir" -Path $testpath -ItemType "directory" -Force
BeforeAll {
$testdirectory = Join-Path -Path $testpath -ChildPath testdir
$testsubdirectory = Join-Path -Path $testdirectory -ChildPath subd
}
Test-Path $testdirectory | Should -BeTrue
}
BeforeEach {
New-Item -Name "testdir" -Path $testpath -ItemType "directory" -Force
It "Should be able to remove a directory" {
{ Remove-Item $testdirectory } | Should -Not -Throw
Test-Path $testdirectory | Should -BeTrue
}
Test-Path $testdirectory | Should -BeFalse
}
It "Should be able to remove a directory" {
{ Remove-Item $testdirectory -ErrorAction Stop } | Should -Not -Throw
It "Should be able to recursively delete subfolders" {
New-Item -Name "subd" -Path $testdirectory -ItemType "directory"
New-Item -Name $testfile -Path $testsubdirectory -ItemType "file" -Value "lorem ipsum"
Test-Path $testdirectory | Should -BeFalse
}
$complexDirectory = Join-Path -Path $testsubdirectory -ChildPath $testfile
Test-Path $complexDirectory | Should -BeTrue
It "Should be able to recursively delete subfolders" {
New-Item -Name "subd" -Path $testdirectory -ItemType "directory"
New-Item -Name $testfile -Path $testsubdirectory -ItemType "file" -Value "lorem ipsum"
{ Remove-Item $testdirectory -Recurse} | Should -Not -Throw
$complexDirectory = Join-Path -Path $testsubdirectory -ChildPath $testfile
Test-Path $complexDirectory | Should -BeTrue
Test-Path $testdirectory | Should -BeFalse
}
{ Remove-Item $testdirectory -Recurse -ErrorAction Stop } | Should -Not -Throw
Test-Path $testdirectory | Should -BeFalse
}
It "Should be able to recursively delete a directory with a trailing backslash" {
New-Item -Name "subd" -Path $testdirectory -ItemType "directory"
New-Item -Name $testfile -Path $testsubdirectory -ItemType "file" -Value "lorem ipsum"
$complexDirectory = Join-Path -Path $testsubdirectory -ChildPath $testfile
Test-Path $complexDirectory | Should -BeTrue
$testdirectoryWithBackSlash = Join-Path -Path $testdirectory -ChildPath ([IO.Path]::DirectorySeparatorChar)
Test-Path $testdirectoryWithBackSlash | Should -BeTrue
{ Remove-Item $testdirectoryWithBackSlash -Recurse -ErrorAction Stop } | Should -Not -Throw
Test-Path $testdirectoryWithBackSlash | Should -BeFalse
Test-Path $testdirectory | Should -BeFalse
}
}
Context "Alternate Data Streams should be supported on Windows" {
BeforeAll {
if (!$IsWindows) {
return
}
$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
BeforeAll {
if (!$IsWindows) {
return
}
$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
$null = New-Item -Path $streamfile -ItemType "File" -force
Add-Content -Path $streamfile -Value $fileContent
Add-Content -Path $streamfile -Stream $streamName -Value $streamContent
$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) {
Get-Item -Path $streamfile -Stream $streamName | Should -Not -BeNullOrEmpty
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) {
Get-Item -Path $streamdir -Stream $streamName | Should -Not -BeNullOrEmpty
Remove-Item -Path $streamdir -Stream $streamName
Get-Item -Path $streamdir -Stream $streamname -ErrorAction SilentlyContinue | Should -BeNullOrEmpty
}
$null = New-Item -Path $streamfile -ItemType "File" -force
Add-Content -Path $streamfile -Value $fileContent
Add-Content -Path $streamfile -Stream $streamName -Value $streamContent
$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) {
Get-Item -Path $streamfile -Stream $streamName | Should -Not -BeNullOrEmpty
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) {
Get-Item -Path $streamdir -Stream $streamName | Should -Not -BeNullOrEmpty
Remove-Item -Path $streamdir -Stream $streamName
Get-Item -Path $streamdir -Stream $streamname -ErrorAction SilentlyContinue | Should -BeNullOrEmpty
}
}
}