Test/04_CIMRegistry_New_Set_Functions.ps1
# This is a Pester test file ##### New Functions #### (the most complex and crucial functions) Describe 'New functions' { #region Mock ## Normal key # Parent key $NormalParentKeyName = 'SOFTWARE\Ankh-Morpork' $NormalParentKeyPath = 'HKEY_LOCAL_MACHINE\' + $NormalParentKeyName Mock Test-cdxmlRegistryKeyAccess { [PSCustomObject]@{ReturnValue = 0; bGranted = $true} } { $PSBoundParameters.Key -eq $NormalParentKeyName } # New subkey $NormalNewKeyName = 'SOFTWARE\Ankh-Morpork\Opera' $NormalNewKeyPath = 'HKEY_LOCAL_MACHINE\' + $NormalNewKeyName Mock New-cdxmlRegistryKey { [PSCustomObject]@{ReturnValue = 0} } { $PSBoundParameters.Key -eq $NormalNewKeyName } Mock Test-cdxmlRegistryKeyAccess { [PSCustomObject]@{ReturnValue = 0; bGranted = $true} } { $PSBoundParameters.Key -eq $NormalNewKeyName } # Existing subkey $ExistingKeyName = 'SOFTWARE\Ankh-Morpork\PseudopolisYard' $ExistingKeyPath = 'HKEY_LOCAL_MACHINE\' + $ExistingKeyName $ESubkeys = @('Floor1','Floor2','Floor3') $Evalues = @('Commander','Captain','Sergeant','Corporal','Lance-Corporal','Constable','ActingConstable','Lance-Constable') $ETypes = @(1,1,1,1,1,1,1,1) Mock New-cdxmlRegistryKey { [PSCustomObject]@{ReturnValue = 0} } { $PSBoundParameters.Key -eq $ExistingKeyName } Mock Test-cdxmlRegistryKeyAccess { [PSCustomObject]@{ReturnValue = 0; bGranted = $true} } { $PSBoundParameters.Key -eq $ExistingKeyName } Mock Get-cdxmlSubkeyName { [PSCustomObject]@{ReturnValue = 2; sNames = $ESubkeys} } { $PSBoundParameters.Key -eq $ExistingKeyName } Mock Get-cdxmlValueName { [PSCustomObject]@{ReturnValue = 2; sNames = $Evalues; Types = $ETypes} } { $PSBoundParameters.Key -eq $ExistingKeyName } ## Values # New value $NewValueName = 'Location' Mock Get-cdxmlStringValue { [PSCustomObject]@{ReturnValue = 0; sValue = 'DiscWorld'} } { ($PSBoundParameters.Key -eq $NormalParentKeyName) -and ($PSBoundParameters.ValueName -eq $NewValueName) } Mock Set-cdxmlStringValue { [PSCustomObject]@{ReturnValue = 0} } { ($PSBoundParameters.Key -eq $NormalParentKeyName) -and ($PSBoundParameters.ValueName -eq $NewValueName) } # Existing value same type $ValueSameTypeName = 'onRiver' Mock Get-cdxmlStringValue { [PSCustomObject]@{ReturnValue = 0; sValue = 'Ankh'} } { ($PSBoundParameters.Key -eq $NormalParentKeyName) -and ($PSBoundParameters.ValueName -eq $ValueSameTypeName) } Mock Set-cdxmlStringValue { [PSCustomObject]@{ReturnValue = 0} } { ($PSBoundParameters.Key -eq $NormalParentKeyName) -and ($PSBoundParameters.ValueName -eq $ValueSameTypeName) } # Existing value other type $ValueOtherTypeName = 'Population' # Mock Get-cdxmlDWORDValue { [PSCustomObject]@{ReturnValue = 0; uValue = 1000000} } { ($PSBoundParameters.Key -eq $NormalNewKeyName) -and ($PSBoundParameters.ValueName -eq $ExistingValueName) } Mock Get-cdxmlStringValue { [PSCustomObject]@{ReturnValue = 2147749893; sValue = $null} } { ($PSBoundParameters.Key -eq $NormalParentKeyName) -and ($PSBoundParameters.ValueName -eq $ValueOtherTypeName) } Mock Set-cdxmlStringValue { [PSCustomObject]@{ReturnValue = 0} } { ($PSBoundParameters.Key -eq $NormalParentKeyName) -and ($PSBoundParameters.ValueName -eq $ValueOtherTypeName) } ## No access key # Parent key $MockNAKeyName = 'SOFTWARE\Ankh-Morpork\Shadows' $MockNAKeyPath = 'HKEY_LOCAL_MACHINE\' + $MockNAKeyName Mock Test-cdxmlRegistryKeyAccess { [PSCustomObject]@{ReturnValue = 5; bGranted = $false} } { $PSBoundParameters.Key -eq $MockNAKeyName } # New key under NoAccess key $MockNewNAKeyName = 'SOFTWARE\Ankh-Morpork\Shadows\Parameters' $MockNewNAKeyPath = 'HKEY_LOCAL_MACHINE\' + $MockNewNAKeyName Mock New-cdxmlRegistryKey { [PSCustomObject]@{ReturnValue = 5} } { $PSBoundParameters.Key -eq $MockNewNAKeyName } Mock Test-cdxmlRegistryKeyAccess { [PSCustomObject]@{ReturnValue = 2; bGranted = $false} } { $PSBoundParameters.Key -eq $MockNewNAKeyName } ## Missing parent key # Parent key $MissingParentKeyName = 'SOFTWARE\Ankh-Morpork\Unseen-U' $MissingParentKeyPath = 'HKEY_LOCAL_MACHINE\' + $MissingParentKeyName Mock Test-cdxmlRegistryKeyAccess { [PSCustomObject]@{ReturnValue = 2; bGranted = $false} } { $PSBoundParameters.Key -eq $MissingParentKeyName } Mock New-cdxmlRegistryKey { [PSCustomObject]@{ReturnValue = 0} } { $PSBoundParameters.Key -eq $MissingParentKeyName } # New key under missing key (created with Force parameter) $MissParentSubKeyName = 'SOFTWARE\Ankh-Morpork\Unseen-U\Library' $MissParentSubKeyPath = 'HKEY_LOCAL_MACHINE\' + $MissParentSubKeyName Mock New-cdxmlRegistryKey { [PSCustomObject]@{ReturnValue = 0} } { $PSBoundParameters.Key -eq $MissParentSubKeyName } # Value under missing key $MissingSubKeyValue = 'TowerHeight' Mock Set-cdxmlDWORDValue { [PSCustomObject]@{ReturnValue = 0} } { ($PSBoundParameters.Key -eq $MissingParentKeyName) -and ($PSBoundParameters.ValueName -eq $MissingSubKeyValue) } #endregion Context 'New-RegistryKey' { $NewKeyResult = New-RegistryKey -Path $NormalNewKeyPath It 'Return the key object if it was created ' { $NewKeyResult.Path | Should -Be $NormalNewKeyPath } It 'Returns new key object with no subkeys/values' { $NewKeyResult.SubKeyCount | Should -BeNullOrEmpty $NewKeyResult.ValueCount | Should -BeNullOrEmpty } It 'Returns existing key object with proper numbers of subkeys/values' { $ExistingResult = New-RegistryKey -Path $ExistingKeyPath $ExistingResult.SubKeyCount | Should -Be 3 $ExistingResult.ValueCount | Should -Be 8 } It 'Throws if it has no permissions on the parent key' { { New-RegistryKey -Path $MockNewNAKeyPath -ErrorAction Stop } | Should -Throw 'Access is denied' } It 'Throws if the parent key does not exist' { { New-RegistryKey -Path $MissParentSubKeyPath -ErrorAction Stop} | Should -Throw 'Registry key does not exist' } It 'Creates a key under missing parent key with Force parameter.' { $NewEnforcedKeyResult = New-RegistryKey -Path $MissParentSubKeyPath -Force $NewEnforcedKeyResult.Path | Should -Be $MissParentSubKeyPath } Context "Call common tests" { & $PSScriptRoot\99_CIMRegistry_CommonTests.ps1 -FunctionName New-RegistryKey -WrongPathReturn NA -CheckOutput } } Context 'Set-RegistryValue' { $PSDefaultParameterValues=@{"Set-RegistryValue:Confirm"=$False} Context 'Output data' { $NewKeyResult = Set-RegistryValue -Path $NormalParentKeyPath -ValueName 'Location' -ValueType REG_SZ -Data 'DiscWorld' It 'Return one object for one value' { @($NewKeyResult).Count | Should -Be 1 } It 'Return an object of a proper type' { ($NewKeyResult.GetType()).Fullname | Should -Be CIMRegistryValue } It 'Return proper Value name' { $NewKeyResult.ValueName | Should -Be 'Location' } It 'Return proper registry type' { $NewKeyResult.ValueType | Should -Be 'REG_SZ' } It 'Return proper data' { $NewKeyResult.Data | Should -Be 'DiscWorld' } It 'ErrorCode must be zero' { $NewKeyResult.ErrorCode | Should -Be 0 } It 'Calls proper cdxml functions for single String value' { Assert-MockCalled Test-cdxmlRegistryKeyAccess -Times 1 -Exactly Assert-MockCalled Get-cdxmlStringValue -Times 1 -Exactly Assert-MockCalled Set-cdxmlStringValue -Times 1 -Exactly } } It 'Works if the existing value has the same type' { { Set-RegistryValue -Path $NormalParentKeyPath -ValueName $ValueSameTypeName -ValueType REG_SZ -Data 'BigRiver' -ErrorAction Stop} | Should -Not -Throw } It 'Throws if the value exits and has other data type' { { Set-RegistryValue -Path $NormalParentKeyPath -ValueName $ValueOtherTypeName -ValueType REG_SZ -Data 'Unknown' -ErrorAction Stop} | Should -Throw 'Type mismatch' Assert-MockCalled Test-cdxmlRegistryKeyAccess -Times 1 -Exactly -Scope it Assert-MockCalled Get-cdxmlStringValue -Times 1 -Exactly -Scope it Assert-MockCalled Set-cdxmlStringValue -Times 0 -Exactly -Scope it } It 'Ignors Type msimatch if Force used' { { Set-RegistryValue -Path $NormalParentKeyPath -ValueName $ValueOtherTypeName -ValueType REG_SZ -Data 'Unknown' -Force -ErrorAction Stop} | Should -Not -Throw Assert-MockCalled Set-cdxmlStringValue -Times 1 -Exactly -Scope it } It 'Throws if the key does not exist' { { Set-RegistryValue -Path $MissingParentKeyPath -ValueName 'Location' -ValueType REG_SZ -Data 'DiscWorld' -ErrorAction Stop} | Should -Throw 'Registry key does not exist' } It 'Creates missing key and value in it if Force used' { $ValUnderNewKey = Set-RegistryValue -Path $MissingParentKeyPath -ValueName $MissingSubKeyValue -ValueType REG_DWORD -Data 800 -ErrorAction Stop -Force Assert-MockCalled New-cdxmlRegistryKey -Times 1 -Exactly -Scope it $ValUnderNewKey.Path | Should -Be $MissingParentKeyPath } It 'Throws if it has no permissions on the key' { { Set-RegistryValue -Path $MockNAKeyPath -ValueName 'Location' -ValueType REG_SZ -Data 'DiscWorld' -ErrorAction Stop} | Should -Throw 'Access is denied' } Context 'Calls poper cdxml functions for each registry type' { $GetValueFunction = 'Get-cdxmlStringValue','Get-cdxmlExpandedStringValue','Get-cdxmlBinaryValue','Get-cdxmlDWORDValue','Get-cdxmlMultiStringValue','Get-cdxmlQWORDValue' $SetValueFunction = 'Set-cdxmlStringValue','Set-cdxmlExpandedStringValue','Set-cdxmlBinaryValue','Set-cdxmlDWORDValue','Set-cdxmlMultiStringValue','Set-cdxmlQWORDValue' $GetValueFunction | ForEach-Object { Mock $_ { [PSCustomObject]@{ReturnValue = 0; sValue = $null} } } $SetValueFunction | ForEach-Object { Mock $_ { [PSCustomObject]@{ReturnValue = 0} } } It 'String (REG_SZ)' { Set-RegistryValue -Path $NormalParentKeyPath -ValueName StringName -ValueType REG_SZ -Data 'String' Assert-MockCalled Set-cdxmlStringValue -Times 1 -Exactly } It 'Expandable String (REG_EXPAND_SZ)' { Set-RegistryValue -Path $NormalParentKeyPath -ValueName ExStringName -ValueType REG_EXPAND_SZ -Data 'ExString' Assert-MockCalled Set-cdxmlExpandedStringValue -Times 1 -Exactly } It 'Binary (REG_BINARY)' { Set-RegistryValue -Path $NormalParentKeyPath -ValueName StringName -ValueType REG_BINARY -Data 123 Assert-MockCalled Set-cdxmlBinaryValue -Times 1 -Exactly } It 'DWORD (REG_DWORD)' { Set-RegistryValue -Path $NormalParentKeyPath -ValueName DwordName -ValueType REG_DWORD -Data 300 Assert-MockCalled Set-cdxmlDWORDValue -Times 1 -Exactly } It 'MultiString (REG_MULTI_SZ)' { Set-RegistryValue -Path $NormalParentKeyPath -ValueName MultiStringName -ValueType REG_MULTI_SZ -Data 'MutliString' Assert-MockCalled Set-cdxmlMultiStringValue -Times 1 -Exactly } It 'QWORD (REG_QWORD)' { Set-RegistryValue -Path $NormalParentKeyPath -ValueName StringName -ValueType REG_QWORD -Data 90000 Assert-MockCalled Set-cdxmlQWORDValue -Times 1 -Exactly } } Context "Call common tests" { & $PSScriptRoot\99_CIMRegistry_CommonTests.ps1 -FunctionName Set-RegistryValue -WrongPathReturn Error -ExtraParams @{ValueName = 'Tst'; ValueType = 'REG_SZ'; Data = '123'} -CheckOutput } } } |