From 21629d3415cea6e6bd756674dc22d52f2b82dedf Mon Sep 17 00:00:00 2001 From: Raimund Andree Date: Wed, 21 Oct 2026 13:14:58 +0000 Subject: [PATCH] test(items,owner,access): bind four parameters by property name The coverage record of Handoff 5 listed getters of parameters that take pipeline input by property name and that no test bound that way: -Destination of Copy-Item2 and Move-Item2, -Account of Set-NTFSOwner, and -Account of Get-NTFSEffectiveAccess (the getters of AccessType, AuditFlags, and the scope and flag parameters of the access and audit cmdlets, and -Algorithm of Get-FileHash2, are bound by tests now). PowerShell calls the getter of such a parameter once per command when a piped object binds it, so a test has to pipe an object that has the property. Each test pipes two objects that name different values and checks that each item gets its own: two destinations for the copied and the moved file (Copy-Item2 and Move-Item2, read back with Get-Content and Test-Path), two owners that only the Restore privilege can assign (Set-NTFSOwner, read back with Get-Acl; elevated only), and the effective access of Everyone, which an allow entry grants, and of Guests, which a deny entry takes away (Get-NTFSEffectiveAccess). Tests only; no product change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: AI Assistant --- Tests/Access.Tests.ps1 | 20 ++++++++++++++ Tests/Owner.Tests.ps1 | 18 +++++++++++++ Tests/ParameterSets.Items.Tests.ps1 | 42 +++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+) diff --git a/Tests/Access.Tests.ps1 b/Tests/Access.Tests.ps1 index 5b70d0f..fbdbb33 100644 --- a/Tests/Access.Tests.ps1 +++ b/Tests/Access.Tests.ps1 @@ -88,6 +88,26 @@ Describe 'Get-NTFSEffectiveAccess' { $result | Should -BeNullOrEmpty } + # Each piped object names its own account, so one call calculates the access of two accounts on the same item. + It 'Should bind -Account by property name and calculate the access of the account that its own object names' { + $file = New-TestSandboxItem -Sandbox $sandbox -Name 'EffectiveAccountByProperty' + Disable-NTFSAccessInheritance -Path $file -RemoveInheritedAccessRules -ErrorAction Stop + Add-NTFSAccess -Path $file -Account 'S-1-1-0' -AccessRights ReadData -ErrorAction Stop + Add-NTFSAccess -Path $file -Account 'S-1-5-32-546' -AccessRights ReadData -AccessType Deny -ErrorAction Stop + $requests = @( + [pscustomobject]@{ Path = $file; Account = 'S-1-1-0' } + [pscustomobject]@{ Path = $file; Account = 'S-1-5-32-546' } + ) + + $result = @($requests | Get-NTFSEffectiveAccess -WarningAction SilentlyContinue -ErrorAction Stop) + + $result | Should -HaveCount 2 + $result[0].Account.Sid | Should -Be 'S-1-1-0' + $result[0].AccessRights.HasFlag([Security2.FileSystemRights2]::ReadData) | Should -BeTrue + $result[1].Account.Sid | Should -Be 'S-1-5-32-546' + $result[1].AccessRights.HasFlag([Security2.FileSystemRights2]::ReadData) | Should -BeFalse + } + It 'Should return an account with access when -ExcludeNoneAccessEntries is used' { $result = @(Get-NTFSEffectiveAccess -Path $effectiveFile -ExcludeNoneAccessEntries -WarningAction SilentlyContinue -ErrorAction Stop) diff --git a/Tests/Owner.Tests.ps1 b/Tests/Owner.Tests.ps1 index 324f749..d923a59 100644 --- a/Tests/Owner.Tests.ps1 +++ b/Tests/Owner.Tests.ps1 @@ -237,6 +237,24 @@ Describe 'Set-NTFSOwner' { ($result.FullName -join '|') | Should -Be ($files -join '|') } + # Each piped object names its own owner; the owners are accounts that only the Restore privilege can assign, so + # that the result differs from the owner that the items have already. + It 'Should bind -Account by property name and give each piped item the owner that its own object names' -Skip:(-not $canAssignAnyOwner) { + $first = New-TestSandboxItem -Sandbox $sandbox -Name 'SetOwnerAccountByPropertyFirst' + $second = New-TestSandboxItem -Sandbox $sandbox -Name 'SetOwnerAccountByPropertySecond' + $administrators = 'S-1-5-32-544' + $requests = @( + [pscustomobject]@{ Path = $first; Account = $trustedInstaller } + [pscustomobject]@{ Path = $second; Account = $administrators } + ) + + $result = @($requests | Set-NTFSOwner -PassThru -ErrorAction Stop) + + $result | Should -HaveCount 2 + Get-TestOwner -Path $first | Should -Be $trustedInstaller + Get-TestOwner -Path $second | Should -Be $administrators + } + It 'Should set an owner that only the Restore privilege allows' -Skip:(-not $canAssignAnyOwner) { $file = New-TestSandboxItem -Sandbox $sandbox -Name 'SetOwnerRestore' diff --git a/Tests/ParameterSets.Items.Tests.ps1 b/Tests/ParameterSets.Items.Tests.ps1 index 7805650..1e4ae31 100644 --- a/Tests/ParameterSets.Items.Tests.ps1 +++ b/Tests/ParameterSets.Items.Tests.ps1 @@ -1206,6 +1206,48 @@ Describe 'Get-FileHash2 binds -Algorithm by property name' { } } +Describe 'Copy-Item2 and Move-Item2 bind -Destination by property name' { + # A piped object binds -Destination by its own property, so two objects can go to two destinations in one call. + It ' should put each piped item in the destination that its own object names' -ForEach @( + @{ Command = 'Copy-Item2' } + @{ Command = 'Move-Item2' } + ) { + $folder = New-TestSandboxItem -Sandbox $sandbox -Name "DestinationByProperty$Command" -Directory + $destinationOne = Join-Path -Path $folder -ChildPath 'One' + $destinationTwo = Join-Path -Path $folder -ChildPath 'Two' + $first = Join-Path -Path $folder -ChildPath 'First.txt' + $second = Join-Path -Path $folder -ChildPath 'Second.txt' + Assert-TestSandboxPath -Sandbox $sandbox -Path $destinationOne, $destinationTwo, $first, $second + New-Item -ItemType Directory -Path $destinationOne, $destinationTwo | Out-Null + Set-Content -LiteralPath $first -Value 'First' + Set-Content -LiteralPath $second -Value 'Second' + $requests = @( + [pscustomobject]@{ Path = $first; Destination = $destinationOne } + [pscustomobject]@{ Path = $second; Destination = $destinationTwo } + ) + + $result = @($requests | & $Command -PassThru $true -ErrorAction Stop) + + $copiedFirst = Join-Path -Path $destinationOne -ChildPath 'First.txt' + $copiedSecond = Join-Path -Path $destinationTwo -ChildPath 'Second.txt' + $result | Should -HaveCount 2 + $result[0].FullName | Should -Be $copiedFirst + $result[1].FullName | Should -Be $copiedSecond + Get-Content -LiteralPath $copiedFirst | Should -Be 'First' + Get-Content -LiteralPath $copiedSecond | Should -Be 'Second' + (Join-Path -Path $destinationOne -ChildPath 'Second.txt') | Should -Not -Exist + (Join-Path -Path $destinationTwo -ChildPath 'First.txt') | Should -Not -Exist + if ($Command -eq 'Copy-Item2') { + $first | Should -Exist + $second | Should -Exist + } + else { + $first | Should -Not -Exist + $second | Should -Not -Exist + } + } +} + Describe 'Get-DiskSpace free-space values and validation error' { It 'Should report free-space values close to an independent .NET read for the system drive' { $before = New-Object -TypeName 'System.IO.DriveInfo' -ArgumentList $env:SystemDrive