From c816a0951588a7d01481613bfab85fa7600aa830 Mon Sep 17 00:00:00 2001 From: NicolasB Date: Fri, 10 Sep 2021 11:52:20 +0200 Subject: [PATCH] Fixed Compare-DscParameterState returning false positive when parameter with an empty hashtable or CimInstance property is passed in DesriedValues - fixes issue #65 (#76) --- CHANGELOG.md | 16 + source/Public/Compare-DscParameterState.ps1 | 43 +- source/en-US/DscResource.Common.strings.psd1 | 1 + .../Compare-DscParameterState.Tests.ps1 | 434 +++++++++++++++++- 4 files changed, 481 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7403a6..ab20ad4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- Correction to `Compare-DscParameterState` returning false positive when parameter + with an empty hashtable or CimInstance property is passed in `DesriedValues` - fixes + [issue #65](https://github.com/dsccommunity/DscResource.Common/issues/65). +- Correction somes problems in `Compare-DscParameterState` - see [issue #70](https://github.com/dsccommunity/DscResource.Common/issues/70) : + - When you use `-ReverseCheck`, this value is used in recursive call of + `Test-DscParameterState` and `Compare-DscParameterState`, and that called + another time the function. + - When you use `-Properties` and `-ReverseCheck`, and you have an array in member, + that return a wrong value, because the properties are set in recursive calls of + `-ReverseCheck` to test the value of array. + - When you use `-ReverseCheck` and, in the function `Test-DscCompareState`/`Compare-DscParameterState` + are recursively called (like to test or compare value of array), `-ReverseCheck` + value is removed from `$PSBoundParameters`. And the ReverseCheck isn't done. + ## [0.10.3] - 2021-06-26 ### Added diff --git a/source/Public/Compare-DscParameterState.ps1 b/source/Public/Compare-DscParameterState.ps1 index ef38941..57ae442 100644 --- a/source/Public/Compare-DscParameterState.ps1 +++ b/source/Public/Compare-DscParameterState.ps1 @@ -322,6 +322,12 @@ function Compare-DscParameterState $InDesiredStateTable.InDesiredState = $false continue # pass to the next key } + elseif ($desiredType.Name -eq 'Unknown' -and $desiredType.Name -ne $currentType.Name) + { + Write-Verbose -Message ($script:localizedData.NoMatchTypeMismatchMessage -f $key, $currentType.Name, $desiredType.Name) + $InDesiredStateTable.InDesiredState = $false + continue # pass to the next key + } } #endregion TestType #region Check if the value of Current and desired state is the same but only if they are not an array @@ -331,7 +337,7 @@ function Compare-DscParameterState continue # pass to the next key } #endregion check same value - #region Check if the DesiredValuesClean has the key and if it don't have, it's not necessary to check his value + #region Check if the DesiredValuesClean has the key and if it doesn't have, it's not necessary to check his value if ($desiredValuesClean.GetType().Name -in 'HashTable', 'PSBoundParametersDictionary') { $checkDesiredValue = $desiredValuesClean.ContainsKey($key) @@ -455,11 +461,11 @@ function Compare-DscParameterState if ($desiredType -eq [System.Collections.Hashtable] -and $currentType -eq [System.Collections.Hashtable]) { - $param = $PSBoundParameters + $param = @{} + $PSBoundParameters $param.CurrentValues = $currentArrayValues[$i] $param.DesiredValues = $desiredArrayValues[$i] - 'IncludeInDesiredState','IncludeValue' | ForEach-Object { + 'IncludeInDesiredState','IncludeValue','Properties','ReverseCheck' | ForEach-Object { if ($param.ContainsKey($_)) { $null = $param.Remove($_) @@ -494,11 +500,11 @@ function Compare-DscParameterState } elseif ($desiredType -eq [System.Collections.Hashtable] -and $currentType -eq [System.Collections.Hashtable]) { - $param = $PSBoundParameters + $param = @{} + $PSBoundParameters $param.CurrentValues = $currentValue $param.DesiredValues = $desiredValue - 'IncludeInDesiredState','IncludeValue' | ForEach-Object { + 'IncludeInDesiredState','IncludeValue','Properties','ReverseCheck' | ForEach-Object { if ($param.ContainsKey($_)) { $null = $param.Remove($_) @@ -507,11 +513,22 @@ function Compare-DscParameterState if ($InDesiredStateTable.InDesiredState) { - $InDesiredStateTable.InDesiredState = Test-DscParameterState @param + <# + if desiredvalue is an empty hashtable and not currentvalue, it's not necessery to compare them, it's not compliant. + See issue 65 https://github.com/dsccommunity/DscResource.Common/issues/65 + #> + if ($desiredValue.Keys.Count -eq 0 -and $currentValue.Keys.Count -ne 0) + { + Write-Verbose -Message ($script:localizedData.NoMatchKeyMessage -f $desiredType.FullName, $key, $($currentValue.Keys -join ', ')) + $InDesiredStateTable.InDesiredState = $false + } + else{ + $InDesiredStateTable.InDesiredState = Test-DscParameterState @param + } } else { - Test-DscParameterState @param | Out-Null + $null = Test-DscParameterState @param } continue } @@ -555,9 +572,15 @@ function Compare-DscParameterState if ($ReverseCheck) { Write-Verbose -Message $script:localizedData.StartingReverseCheck - $reverseCheckParameters = $PSBoundParameters - $reverseCheckParameters.CurrentValues = $DesiredValues - $reverseCheckParameters.DesiredValues = $CurrentValues + $reverseCheckParameters = @{} + $PSBoundParameters + $reverseCheckParameters['CurrentValues'] = $DesiredValues + $reverseCheckParameters['DesiredValues'] = $CurrentValues + $reverseCheckParameters['Properties'] = $keyList + $CurrentValues.Keys | Select-Object -Unique + if ($ExcludeProperties) + { + $reverseCheckParameters['Properties'] = $reverseCheckParameters['Properties'] | Where-Object -FilterScript { $_ -notin $ExcludeProperties } + } + $null = $reverseCheckParameters.Remove('ReverseCheck') if ($returnValue) diff --git a/source/en-US/DscResource.Common.strings.psd1 b/source/en-US/DscResource.Common.strings.psd1 index 14c3a4f..c1bc85b 100644 --- a/source/en-US/DscResource.Common.strings.psd1 +++ b/source/en-US/DscResource.Common.strings.psd1 @@ -35,4 +35,5 @@ ConvertFrom-StringData @' PropertyInDesiredState = The parameter '{0}' is in desired state. (DRC0039) PropertyNotInDesiredState = The parameter '{0}' is not in desired state. (DRC0040) PropertyNotInDesiredStateMessage = Property '{0}' is not in desired state. (DRC0041) + NoMatchKeyMessage = NOTMATCH: Value (type '{0}') for property '{1}' does not match. Current state has the key(s) '{2}' and desired state has not. (DRC0042) '@ diff --git a/tests/Unit/Public/Compare-DscParameterState.Tests.ps1 b/tests/Unit/Public/Compare-DscParameterState.Tests.ps1 index 2544068..6b1692d 100644 --- a/tests/Unit/Public/Compare-DscParameterState.Tests.ps1 +++ b/tests/Unit/Public/Compare-DscParameterState.Tests.ps1 @@ -10,7 +10,7 @@ BeforeAll { Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { BeforeAll { - $verbose = $true + $verbose = $false } Context 'When testing single values' { @@ -79,6 +79,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for String InDesiredState' { $script:result.Where({ $_.Property -eq 'String' @@ -122,6 +126,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for Bool InDesiredState' { $script:result.Where({ $_.Property -eq 'Bool' @@ -165,6 +173,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for Int InDesiredState' { $script:result.Where({ $_.Property -eq 'Int' @@ -209,6 +221,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for ScriptBlock InDesiredState' { $script:result.Where({ $_.Property -eq 'ScriptBlock' @@ -252,6 +268,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for Int InDesiredState' { $script:result.Where({ $_.Property -eq 'Int' @@ -290,6 +310,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for Int InDesiredState' { $script:result.Where({ $_.Property -eq 'Int' @@ -436,6 +460,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for String InDesiredState' { $script:result.Where({ $_.Property -eq 'String' @@ -499,6 +527,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return all InDesiredState in $true' { $script:result.InDesiredState | Should -Not -Contain $false } @@ -527,6 +559,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for String InDesiredState' { $script:result.Where({ $_.Property -eq 'String' @@ -563,6 +599,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for Bool InDesiredState' { $script:result.Where({ $_.Property -eq 'Bool' @@ -599,6 +639,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for Int InDesiredState' { $script:result.Where({ $_.Property -eq 'Int' @@ -636,6 +680,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for ScriptBlock InDesiredState' { $script:result.Where({ $_.Property -eq 'ScriptBlock' @@ -672,6 +720,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for Int InDesiredState' { $script:result.Where({ $_.Property -eq 'Int' @@ -709,6 +761,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for Int InDesiredState' { $script:result.Where({ $_.Property -eq 'Int' @@ -741,6 +797,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $true for Int InDesiredState' { $script:result.Where({ $_.Property -eq 'Int' @@ -781,6 +841,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return all InDesiredState in $true' { $script:result.InDesiredState | Should -Not -Contain $false } @@ -826,6 +890,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return all InDesiredState in $true' { $script:result.InDesiredState | Should -Not -Contain $false } @@ -848,6 +916,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return all InDesiredState in $true' { $script:result.InDesiredState | Should -Not -Contain $false } @@ -881,6 +953,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for String InDesiredState' { $script:result.Where({ $_.Property -eq 'String' @@ -960,6 +1036,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return all InDesiredState in $true' { $script:result.InDesiredState | Should -Not -Contain $false } @@ -993,6 +1073,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for PSCredential InDesiredState' { $script:result.Where({ $_.Property -eq 'PSCredential' @@ -1052,6 +1136,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return all InDesiredState in $true' { $script:result.InDesiredState | Should -Not -Contain $false } @@ -1085,6 +1173,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for PSCredential InDesiredState' { $script:result.Where({ $_.Property -eq 'PSCredential' @@ -1138,6 +1230,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for Array InDesiredState' { $script:result.Where({ $_.Property -eq 'Array' @@ -1169,6 +1265,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for Array InDesiredState' { $script:result.Where({ $_.Property -eq 'Array' @@ -1200,6 +1300,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for Array InDesiredState' { $script:result.Where({ $_.Property -eq 'Array' @@ -1229,6 +1333,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for Array InDesiredState' { $script:result.Where({ $_.Property -eq 'Array' @@ -1259,6 +1367,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $true for Array InDesiredState' { $script:result.Where({ $_.Property -eq 'Array' @@ -1290,6 +1402,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for Array InDesiredState' { $script:result.Where({ $_.Property -eq 'Array' @@ -1322,6 +1438,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $true for Array InDesiredState' { $script:result.Where({ $_.Property -eq 'Array' @@ -1370,6 +1490,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $true for Array InDesiredState' { $script:result.Where({ $_.Property -eq 'Array' @@ -1418,6 +1542,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for Array InDesiredState' { $script:result.Where({ $_.Property -eq 'Array' @@ -1466,6 +1594,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for Array InDesiredState' { $script:result.Where({ $_.Property -eq 'Array' @@ -1518,6 +1650,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for Hashtable InDesiredState' { $script:result.Where({ $_.Property -eq 'Hashtable' @@ -1554,6 +1690,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for Hashtable InDesiredState' { $script:result.Where({ $_.Property -eq 'Hashtable' @@ -1590,6 +1730,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for Hashtable InDesiredState' { $script:result.Where({ $_.Property -eq 'Hashtable' @@ -1626,6 +1770,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for Hashtable InDesiredState' { $script:result.Where({ $_.Property -eq 'Hashtable' @@ -1663,6 +1811,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $true for Hashtable InDesiredState' { $script:result.Where({ $_.Property -eq 'Hashtable' @@ -1699,6 +1851,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for Hashtable InDesiredState' { $script:result.Where({ $_.Property -eq 'Hashtable' @@ -1736,6 +1892,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $true for Hashtable InDesiredState' { $script:result.Where({ $_.Property -eq 'Hashtable' @@ -1781,12 +1941,34 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { { $script:result = Compare-DscParameterState ` -CurrentValues $currentValues ` -DesiredValues $desiredValues ` + -ReverseCheck ` -IncludeInDesiredState ` -Verbose:$verbose } | Should -Not -Throw } - It 'Should return $false for all InDesiredState' { - $script:result.InDesiredState | Should -Not -Contain $false + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + + It 'Should return $true for property Array and Hashtable' { + $script:result.Where({ + $_.Property -eq 'Array' + }).InDesiredState | Should -BeTrue + $script:result.Where({ + $_.Property -eq 'Hashtable' + }).InDesiredState | Should -BeTrue + } + + It 'Should return $false for property String, Bool, Int' { + $script:result.Where({ + $_.Property -eq 'String' + }).InDesiredState | Should -BeFalse + $script:result.Where({ + $_.Property -eq 'Bool' + }).InDesiredState | Should -BeFalse + $script:result.Where({ + $_.Property -eq 'Int' + }).InDesiredState | Should -BeFalse } } @@ -1811,6 +1993,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for missed property (Bool)' { $script:result.Where({ $_.Property -eq 'Bool' @@ -1823,6 +2009,66 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { }).InDesiredState | Should -Not -Contain $false } } + + Context 'When desired state has one more property' { + BeforeAll { + $desiredValues = [PSObject] @{ + String = 'a string' + Bool = $true + Int = 99 + Array = 'a', 'b', 'c', 1 + ArrayTest = 'a', 'b', 'c', 1 + Hashtable = @{ + k1 = 'Test' + k2 = 123 + k3 = 'v1', 'v2', 'v3' + } + } + } + + It 'Should not throw exception' { + { $script:result = Compare-DscParameterState ` + -CurrentValues $currentValues ` + -DesiredValues $desiredValues ` + -ReverseCheck ` + -IncludeInDesiredState ` + -Verbose:$true } | Should -Not -Throw + } + + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + + It 'Should return $true for property Array, Hashtable, String, Bool and Int' { + $script:result.Where({ + $_.Property -eq 'Array' + }).InDesiredState | Should -BeTrue + $script:result.Where({ + $_.Property -eq 'Hashtable' + }).InDesiredState | Should -BeTrue + $script:result.Where({ + $_.Property -eq 'String' + }).InDesiredState | Should -BeTrue + $script:result.Where({ + $_.Property -eq 'Bool' + }).InDesiredState | Should -BeTrue + $script:result.Where({ + $_.Property -eq 'Int' + }).InDesiredState | Should -BeTrue + } + + It 'Should return not null value for property ArrayTest' { + $script:result.Where({ + $_.Property -eq 'ArrayTest' + }).InDesiredState | Should -Not -BeNullOrEmpty + } + + It 'Should return $false for property ArrayTest' { + $script:result.Where({ + $_.Property -eq 'ArrayTest' + }).InDesiredState | Should -BeFalse + } + } } Context 'When testing parameter types' { @@ -1920,6 +2166,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return all InDesiredState in $true' { $script:result.InDesiredState | Should -Not -Contain $false } @@ -1953,6 +2203,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return all InDesiredState in $true' { $script:result.InDesiredState | Should -Not -Contain $false } @@ -1987,6 +2241,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for CimInstances InDesiredState' { $script:result.Where({ $_.Property -eq 'CimInstances' @@ -2030,6 +2288,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for CimInstances InDesiredState' { $script:result.Where({ $_.Property -eq 'CimInstances' @@ -2072,6 +2334,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for CimInstances InDesiredState' { $script:result.Where({ $_.Property -eq 'CimInstances' @@ -2114,6 +2380,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $false for CimInstances InDesiredState' { $script:result.Where({ $_.Property -eq 'CimInstances' @@ -2157,6 +2427,10 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { -Verbose:$verbose } | Should -Not -Throw } + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + It 'Should return $true for CimInstances InDesiredState' { $script:result.Where({ $_.Property -eq 'CimInstances' @@ -2169,5 +2443,159 @@ Describe 'ComputerManagementDsc.Common\Compare-DscParameterState' { }).InDesiredState | Should -Not -Contain $false } } + + # Test added to cover issue #65 https://github.com/dsccommunity/DscResource.Common/issues/65 + Context "When a property is empty in DesriredValues" { + BeforeAll { + $nameServers = [Microsoft.Management.Infrastructure.CimInstance[]] @( + New-CimInstance -ClassName 'MSFT_KeyValuePair' -Namespace 'root/microsoft/Windows/DesiredStateConfiguration' -Property @{ + Key = 'B.ROOT-SERVERS.NET.' + Value = '199.9.14.201' + } -ClientOnly + + New-CimInstance -ClassName 'MSFT_KeyValuePair' -Namespace 'root/microsoft/Windows/DesiredStateConfiguration' -Property @{ + Key = 'M.ROOT-SERVERS.NET.' + Value = '202.12.27.33' + } -ClientOnly + ) + } + Context 'When one property is an empty array in CurrentValues and -ReverseCheck, -TurnOffTypeChecking are used' { + BeforeAll { + $desiredValues = @{ + NameServers = $nameServers + IsSingleInstance = 'Yes' + Verbose = $true + } + + $currentValues = @{ + IsSingleInstance = 'Yes' + NameServers = @() + } + } + + It 'Should not throw' { + $script:compareTargetResourceStateResult = Compare-DscParameterState -CurrentValues $currentValues ` + -DesiredValues $desiredValues ` + -TurnOffTypeChecking ` + -ReverseCheck ` + -Verbose:$verbose + } + + It 'Should not be Null or Empty' { + $script:compareTargetResourceStateResult | Should -Not -BeNullOrEmpty + } + + It 'Should have one value' { + $script:compareTargetResourceStateResult | Should -HaveCount 1 + } + + It 'Should be False in InDesiredState' { + $script:compareTargetResourceStateResult.InDesiredState | Should -BeFalse + } + } + + Context 'When one property is an empty collection of CimInstance in CurrentValues and -ReverseCheck, -TurnOffTypeChecking are used' { + BeforeAll { + $desiredValues = @{ + NameServers = $nameServers + IsSingleInstance = 'Yes' + Verbose = $true + } + + $currentValues = @{ + IsSingleInstance = 'Yes' + NameServers = [Microsoft.Management.Infrastructure.CimInstance[]]@() + } + } + + It 'Should not throw' { + $script:compareTargetResourceStateResult = Compare-DscParameterState -CurrentValues $currentValues ` + -DesiredValues $desiredValues ` + -TurnOffTypeChecking ` + -ReverseCheck ` + -Verbose:$verbose + } + + It 'Should not be Null or Empty' { + $script:compareTargetResourceStateResult | Should -Not -BeNullOrEmpty + } + + It 'Should have one value' { + $script:compareTargetResourceStateResult | Should -HaveCount 1 + } + + It 'Should be False in InDesiredState' { + $script:compareTargetResourceStateResult.InDesiredState | Should -BeFalse + } + } + + Context 'When one property is an empty array in DesiredValues and -TurnOffTypeChecking is used' { + BeforeAll { + $desiredValues = @{ + NameServers = @() + IsSingleInstance = 'Yes' + Verbose = $true + } + + $currentValues = @{ + IsSingleInstance = 'Yes' + NameServers = $nameServers + } + } + + It 'Should not throw' { + $script:compareTargetResourceStateResult = Compare-DscParameterState -CurrentValues $currentValues ` + -DesiredValues $desiredValues ` + -TurnOffTypeChecking ` + -Verbose:$verbose + } + + It 'Should not be Null or Empty' { + $script:compareTargetResourceStateResult | Should -Not -BeNullOrEmpty + } + + It 'Should have one value' { + $script:compareTargetResourceStateResult | Should -HaveCount 1 + } + + It 'Should be False in InDesiredState' { + $script:compareTargetResourceStateResult.InDesiredState | Should -BeFalse + } + } + + Context 'When one property is an empty collection of CimInstance in DesiredValues and -TurnOffTypeChecking is used' { + BeforeAll { + $desiredValues = @{ + NameServers = [Microsoft.Management.Infrastructure.CimInstance[]] @() + IsSingleInstance = 'Yes' + Verbose = $true + } + + $currentValues = @{ + IsSingleInstance = 'Yes' + NameServers = $nameServers + } + } + + It 'Should not throw' { + $script:compareTargetResourceStateResult = Compare-DscParameterState -CurrentValues $currentValues ` + -DesiredValues $desiredValues ` + -TurnOffTypeChecking ` + -Verbose:$verbose + } + + It 'Should not be Null or Empty' { + $script:compareTargetResourceStateResult | Should -Not -BeNullOrEmpty + } + + It 'Should have one value' { + $script:compareTargetResourceStateResult | Should -HaveCount 1 + } + + It 'Should be False in InDesiredState' { + $script:compareTargetResourceStateResult.InDesiredState | Should -BeFalse + } + } + } } }