Test/Set-AclItemOwner.Tests.ps1
|
using namespace System using namespace System.IO using namespace System.Security.Cryptography using namespace System.Collections.Immutable Set-StrictMode -Version Latest # Evaluated at discovery time so -Skip resolves while Pester builds the tree. $IsElevatedHost = $false if ($IsWindows) { $principal = [Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent() $IsElevatedHost = $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) } BeforeAll { $moduleRoot = Split-Path -Path $PSScriptRoot -Parent Import-Module (Join-Path -Path $moduleRoot -ChildPath 'PSSecurity.psd1') -Force } AfterAll { Remove-Module PSSecurity -Force -ErrorAction SilentlyContinue } #### <h2 style="color: #DCA657;">Set-AclItemOwner</h2> #### Describe 'Set-AclItemOwner' -Skip:(-not $IsWindows) { #### #### <b style="color: #D2A8FF;">Cases</b> #### #### - The function is exported, and is a function rather than an alias. It 'Is exported as a function' { $cmd = Get-Command -Module PSSecurity -Name 'Set-AclItemOwner' -ErrorAction SilentlyContinue $cmd | Should -Not -BeNullOrEmpty $cmd.CommandType | Should -Be 'Function' } #### - The composition `Get-AclItem | Set-AclItemOwner` is reachable, and the #### mutator declares ShouldProcess so `-WhatIf` is available. It 'Takes an AclItem from the pipeline and supports ShouldProcess' { $cmd = Get-Command -Module PSSecurity -Name 'Set-AclItemOwner' # Attributes holds every attribute on the parameter, and only the # ParameterAttribute carries ValueFromPipeline. $parameterAttribute = $cmd.Parameters['AclItem'].Attributes | Where-Object { $_ -is [Parameter] } | Select-Object -First 1 $parameterAttribute.ValueFromPipeline | Should -BeTrue $cmd.Parameters.Keys | Should -Contain 'WhatIf' } } #### #### --- #### #### <h2 style="color: #DCA657;">Set-AclItemOwner elevated</h2> #### #### The Administrators account name is resolved from its well known SID rather than #### hardcoded, so these cases pass on a non English Windows install. #### Describe 'Set-AclItemOwner elevated' -Skip:(-not $IsElevatedHost) { BeforeAll { $script:dir = Join-Path ([IO.Path]::GetTempPath()) ([guid]::NewGuid().ToString()) New-Item -ItemType Directory -Path $script:dir | Out-Null $script:fileA = Join-Path $script:dir 'a.txt' $script:fileB = Join-Path $script:dir 'b.txt' Set-Content -LiteralPath $script:fileA -Value 'a' -NoNewline Set-Content -LiteralPath $script:fileB -Value 'b' -NoNewline $script:me = "$($env:USERDOMAIN)\$($env:USERNAME)" $script:administrators = ([Security.Principal.SecurityIdentifier]::new( [Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid, $null )).Translate([Security.Principal.NTAccount]).Value } AfterAll { Remove-Item -LiteralPath $script:dir -Recurse -Force -ErrorAction SilentlyContinue } #### #### <b style="color: #D2A8FF;">Cases</b> #### #### - The returned item carries the new owner, and identifies the file it changed. It 'Returns the re-read item with the new owner' { $result = $script:fileA | Get-AclItem | Set-AclItemOwner -Identity $script:administrators $result.Owner | Should -Be $script:administrators $result.FullName | Should -Be $script:fileA } #### - The change survives a fresh read, so the return value reflects disk and #### not just what the function intended to do. It 'Persists the change to disk' { $script:fileA | Get-AclItem | Set-AclItemOwner -Identity $script:me | Out-Null (Get-AclItem -LiteralPath $script:fileA).Owner | Should -Be $script:me } #### - Omitting `-Identity` falls back to the current user. It 'Defaults the identity to the current user' { $script:fileB | Get-AclItem | Set-AclItemOwner -Identity $script:administrators | Out-Null $result = $script:fileB | Get-AclItem | Set-AclItemOwner $result.Owner | Should -Be $script:me } #### - `-WhatIf` reaches the ShouldProcess branch and writes nothing. It 'Leaves the owner alone under WhatIf' { $script:fileB | Get-AclItem | Set-AclItemOwner -Identity $script:administrators | Out-Null $script:fileB | Get-AclItem | Set-AclItemOwner -Identity $script:me -WhatIf | Out-Null (Get-AclItem -LiteralPath $script:fileB).Owner | Should -Be $script:administrators } #### - A foreign object fails rather than silently mutating something. It 'Rejects an object that did not come from Get-AclItem' { # FileInfo carries FullName, so the guard in Set-AclItemOwner lets it through # and the failure lands on the missing Owner property instead of the usage # message. Asserting only that it throws keeps this test honest either way. { Get-Item -LiteralPath $script:fileA | Set-AclItemOwner -Identity $script:me } | Should -Throw } } #### #### --- #### |