From 017178bc83e73baa3d2db986b5302204af1f2c0c Mon Sep 17 00:00:00 2001 From: Raimund Andree Date: Mon, 13 Oct 2025 16:35:33 +0200 Subject: [PATCH 1/9] Added test to check for issue Single-valued arrays are treated as strings, this causes wrong result Fixes #184 --- .../Public/Test-DscParameterState.Tests.ps1 | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/tests/Unit/Public/Test-DscParameterState.Tests.ps1 b/tests/Unit/Public/Test-DscParameterState.Tests.ps1 index 3eea1f3..738a3b0 100644 --- a/tests/Unit/Public/Test-DscParameterState.Tests.ps1 +++ b/tests/Unit/Public/Test-DscParameterState.Tests.ps1 @@ -294,6 +294,34 @@ Describe 'Test-DscParameterState' { } } + Context 'When there is a single-valued array and TurnOffTypeChecking is used' { + BeforeAll { + $desiredValues = [PSObject] @{ + String = 'a string' + Bool = $true + Int = '99' + Array = 'a', 'b', 'c' + SingleValueArray = 'v1' #Using a string by purpose to test single value array handling + } + } + + It 'Should not throw exception' { + { Test-DscParameterState ` + -CurrentValues $currentValues ` + -DesiredValues $desiredValues ` + -TurnOffTypeChecking ` + -Verbose:$verbose } | Should -Not -Throw + } + + It 'Should return $false' { + Test-DscParameterState ` + -CurrentValues $currentValues ` + -DesiredValues $desiredValues ` + -TurnOffTypeChecking ` + -Verbose:$verbose | Should -BeFalse + } + } + Context 'When a value is mismatched but ExcludeProperties is used to exclude then' { BeforeAll { $desiredValues = @{ @@ -400,6 +428,7 @@ Describe 'Test-DscParameterState' { Bool = $true Int = 99 Array = 'a', 'b', 'c', 1 + SingleValueArray = 'v1', 'v2' #for testing the comparison of single value arrays in the desired state Hashtable = @{ k1 = 'Test' k2 = 123 @@ -943,6 +972,34 @@ Describe 'Test-DscParameterState' { -Verbose:$verbose | Should -BeTrue } } + + Context 'When an array in the desired state has one value and TurnOffTypeChecking is used' { + BeforeAll { + String = 'a string' + $desiredValues = [PSObject] @{ + Bool = $true + Int = 99 + Array = 'a', 'b', 'c', '1' + SingleValueArray = 'v1' + } + } + + It 'Should not throw exception' { + { Test-DscParameterState ` + -CurrentValues $currentValues ` + -DesiredValues $desiredValues ` + -TurnOffTypeChecking ` + -Verbose:$verbose } | Should -Not -Throw + } + + It 'Should return $false' { + Test-DscParameterState ` + -CurrentValues $currentValues ` + -DesiredValues $desiredValues ` + -TurnOffTypeChecking ` + -Verbose:$verbose | Should -BeFalse + } + } } Context 'When reverse checking' { From fc9122298e262d4b04d21bf5c8fd55145a8db92c Mon Sep 17 00:00:00 2001 From: Raimund Andree Date: Mon, 13 Oct 2025 16:37:56 +0200 Subject: [PATCH 2/9] Fixed issue single-valued arrays are treated as strings, this causes wrong result Fixes #184 --- source/Public/Compare-DscParameterState.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Public/Compare-DscParameterState.ps1 b/source/Public/Compare-DscParameterState.ps1 index 3679e1e..8a49961 100644 --- a/source/Public/Compare-DscParameterState.ps1 +++ b/source/Public/Compare-DscParameterState.ps1 @@ -359,7 +359,7 @@ function Compare-DscParameterState } #endregion TestType #region Check if the value of Current and desired state is the same but only if they are not an array - if ($currentValue -eq $desiredValue -and -not $desiredType.IsArray) + if ($currentValue -eq $desiredValue -and -not $desiredType.IsArray -and -not $currentType.IsArray) { Write-Debug -Message ($script:localizedData.MatchValueMessage -f $desiredType.FullName, $key, $currentValue, $desiredValue) continue # pass to the next key From d8aa68daedcb7bfd17ce3c04531faa962c6f488c Mon Sep 17 00:00:00 2001 From: Raimund Andree Date: Mon, 13 Oct 2025 16:38:06 +0200 Subject: [PATCH 3/9] Updated changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ae1cd4..55f2b71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - New-*Exception - Use `ThrowTerminatingError` instead of `throw`. Fixes [#177](https://github.com/dsccommunity/DscResource.Common/issues/177). +- Compare-DscParameterState + - Fixed a bug comparing single-valued arrays in the desired state when + TurnOffTypeChecking is used [#184](https://github.com/dsccommunity/DscResource.Common/issues/184). ## [0.24.2] - 2025-08-27 From 9ce6986584fda29052a4a1258c387c26150f3f79 Mon Sep 17 00:00:00 2001 From: Raimund Andree Date: Mon, 13 Oct 2025 18:31:31 +0200 Subject: [PATCH 4/9] Fixed test data syntax --- tests/Unit/Public/Test-DscParameterState.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Unit/Public/Test-DscParameterState.Tests.ps1 b/tests/Unit/Public/Test-DscParameterState.Tests.ps1 index 738a3b0..6bd9de8 100644 --- a/tests/Unit/Public/Test-DscParameterState.Tests.ps1 +++ b/tests/Unit/Public/Test-DscParameterState.Tests.ps1 @@ -975,8 +975,8 @@ Describe 'Test-DscParameterState' { Context 'When an array in the desired state has one value and TurnOffTypeChecking is used' { BeforeAll { - String = 'a string' $desiredValues = [PSObject] @{ + String = 'a string' Bool = $true Int = 99 Array = 'a', 'b', 'c', '1' From 77c15d280d418b0d85ff2f27f5500f23c43d0308 Mon Sep 17 00:00:00 2001 From: Raimund Andree Date: Mon, 13 Oct 2025 23:10:16 +0200 Subject: [PATCH 5/9] Moving test to the correct context --- .../Public/Test-DscParameterState.Tests.ps1 | 66 +++++++++---------- 1 file changed, 32 insertions(+), 34 deletions(-) diff --git a/tests/Unit/Public/Test-DscParameterState.Tests.ps1 b/tests/Unit/Public/Test-DscParameterState.Tests.ps1 index 6bd9de8..1f06c89 100644 --- a/tests/Unit/Public/Test-DscParameterState.Tests.ps1 +++ b/tests/Unit/Public/Test-DscParameterState.Tests.ps1 @@ -569,7 +569,6 @@ Describe 'Test-DscParameterState' { } } - Context 'When array has a value with a different type' { BeforeAll { $desiredValues = [PSObject] @{ @@ -622,6 +621,38 @@ Describe 'Test-DscParameterState' { } } + Context 'When an array in hashtable has different order but SortArrayValues is used' { + BeforeAll { + $desiredValues = [PSObject] @{ + String = 'a string' + Bool = $true + Int = 99 + Array = 'a', 'b', 'c' + Hashtable = @{ + k1 = 'Test' + k2 = 123 + k3 = 'v3', 'v2', 'v1', 99 + } + } + } + + It 'Should not throw exception' { + { Test-DscParameterState ` + -CurrentValues $currentValues ` + -DesiredValues $desiredValues ` + -SortArrayValues ` + -Verbose:$verbose } | Should -Not -Throw + } + + It 'Should return $true' { + Test-DscParameterState ` + -CurrentValues $currentValues ` + -DesiredValues $desiredValues ` + -SortArrayValues ` + -Verbose:$verbose | Should -BeTrue + } + } + Context 'When both arrays are empty' { BeforeAll { $currentValues = @{ @@ -878,39 +909,6 @@ Describe 'Test-DscParameterState' { } } - Context 'When an array in hashtable has different order but SortArrayValues is used' { - BeforeAll { - $desiredValues = [PSObject] @{ - String = 'a string' - Bool = $true - Int = 99 - Array = 'a', 'b', 'c' - Hashtable = @{ - k1 = 'Test' - k2 = 123 - k3 = 'v3', 'v2', 'v1', 99 - } - } - } - - It 'Should not throw exception' { - { Test-DscParameterState ` - -CurrentValues $currentValues ` - -DesiredValues $desiredValues ` - -SortArrayValues ` - -Verbose:$verbose } | Should -Not -Throw - } - - It 'Should return $true' { - Test-DscParameterState ` - -CurrentValues $currentValues ` - -DesiredValues $desiredValues ` - -SortArrayValues ` - -Verbose:$verbose | Should -BeTrue - } - } - - Context 'When hashtable has a value with a different type' { BeforeAll { $desiredValues = [PSObject] @{ From 1159c309b49169b4e556fabfc5358401d839566b Mon Sep 17 00:00:00 2001 From: Raimund Andree Date: Mon, 13 Oct 2025 23:51:44 +0200 Subject: [PATCH 6/9] Moved test again --- .../Public/Test-DscParameterState.Tests.ps1 | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/tests/Unit/Public/Test-DscParameterState.Tests.ps1 b/tests/Unit/Public/Test-DscParameterState.Tests.ps1 index 1f06c89..6969a43 100644 --- a/tests/Unit/Public/Test-DscParameterState.Tests.ps1 +++ b/tests/Unit/Public/Test-DscParameterState.Tests.ps1 @@ -621,6 +621,34 @@ Describe 'Test-DscParameterState' { } } + Context 'When an array in the desired state has one value and TurnOffTypeChecking is used' { + BeforeAll { + $desiredValues = [PSObject] @{ + String = 'a string' + Bool = $true + Int = 99 + Array = 'a', 'b', 'c', '1' + SingleValueArray = 'v1' + } + } + + It 'Should not throw exception' { + { Test-DscParameterState ` + -CurrentValues $currentValues ` + -DesiredValues $desiredValues ` + -TurnOffTypeChecking ` + -Verbose:$verbose } | Should -Not -Throw + } + + It 'Should return $false' { + Test-DscParameterState ` + -CurrentValues $currentValues ` + -DesiredValues $desiredValues ` + -TurnOffTypeChecking ` + -Verbose:$verbose | Should -BeFalse + } + } + Context 'When an array in hashtable has different order but SortArrayValues is used' { BeforeAll { $desiredValues = [PSObject] @{ @@ -970,34 +998,6 @@ Describe 'Test-DscParameterState' { -Verbose:$verbose | Should -BeTrue } } - - Context 'When an array in the desired state has one value and TurnOffTypeChecking is used' { - BeforeAll { - $desiredValues = [PSObject] @{ - String = 'a string' - Bool = $true - Int = 99 - Array = 'a', 'b', 'c', '1' - SingleValueArray = 'v1' - } - } - - It 'Should not throw exception' { - { Test-DscParameterState ` - -CurrentValues $currentValues ` - -DesiredValues $desiredValues ` - -TurnOffTypeChecking ` - -Verbose:$verbose } | Should -Not -Throw - } - - It 'Should return $false' { - Test-DscParameterState ` - -CurrentValues $currentValues ` - -DesiredValues $desiredValues ` - -TurnOffTypeChecking ` - -Verbose:$verbose | Should -BeFalse - } - } } Context 'When reverse checking' { From 3318bb2bd39f0e188928e03e0495b330dfc3b821 Mon Sep 17 00:00:00 2001 From: Raimund Andree Date: Tue, 14 Oct 2025 09:27:47 +0200 Subject: [PATCH 7/9] Fixed tests for one more time --- .../Public/Test-DscParameterState.Tests.ps1 | 71 +++---------------- 1 file changed, 8 insertions(+), 63 deletions(-) diff --git a/tests/Unit/Public/Test-DscParameterState.Tests.ps1 b/tests/Unit/Public/Test-DscParameterState.Tests.ps1 index 6969a43..4498114 100644 --- a/tests/Unit/Public/Test-DscParameterState.Tests.ps1 +++ b/tests/Unit/Public/Test-DscParameterState.Tests.ps1 @@ -294,34 +294,6 @@ Describe 'Test-DscParameterState' { } } - Context 'When there is a single-valued array and TurnOffTypeChecking is used' { - BeforeAll { - $desiredValues = [PSObject] @{ - String = 'a string' - Bool = $true - Int = '99' - Array = 'a', 'b', 'c' - SingleValueArray = 'v1' #Using a string by purpose to test single value array handling - } - } - - It 'Should not throw exception' { - { Test-DscParameterState ` - -CurrentValues $currentValues ` - -DesiredValues $desiredValues ` - -TurnOffTypeChecking ` - -Verbose:$verbose } | Should -Not -Throw - } - - It 'Should return $false' { - Test-DscParameterState ` - -CurrentValues $currentValues ` - -DesiredValues $desiredValues ` - -TurnOffTypeChecking ` - -Verbose:$verbose | Should -BeFalse - } - } - Context 'When a value is mismatched but ExcludeProperties is used to exclude then' { BeforeAll { $desiredValues = @{ @@ -621,45 +593,18 @@ Describe 'Test-DscParameterState' { } } - Context 'When an array in the desired state has one value and TurnOffTypeChecking is used' { - BeforeAll { - $desiredValues = [PSObject] @{ - String = 'a string' - Bool = $true - Int = 99 - Array = 'a', 'b', 'c', '1' - SingleValueArray = 'v1' - } - } - - It 'Should not throw exception' { - { Test-DscParameterState ` - -CurrentValues $currentValues ` - -DesiredValues $desiredValues ` - -TurnOffTypeChecking ` - -Verbose:$verbose } | Should -Not -Throw - } - - It 'Should return $false' { - Test-DscParameterState ` - -CurrentValues $currentValues ` - -DesiredValues $desiredValues ` - -TurnOffTypeChecking ` - -Verbose:$verbose | Should -BeFalse - } - } - - Context 'When an array in hashtable has different order but SortArrayValues is used' { + Context 'When there is a single-valued array and TurnOffTypeChecking is used' { BeforeAll { $desiredValues = [PSObject] @{ String = 'a string' Bool = $true Int = 99 - Array = 'a', 'b', 'c' + Array = 'a', 'b', 'c', 1 + SingleValueArray = 'v1' #for testing the comparison of single value arrays in the desired state Hashtable = @{ k1 = 'Test' k2 = 123 - k3 = 'v3', 'v2', 'v1', 99 + k3 = 'v1', 'v2', 'v3' } } } @@ -668,16 +613,16 @@ Describe 'Test-DscParameterState' { { Test-DscParameterState ` -CurrentValues $currentValues ` -DesiredValues $desiredValues ` - -SortArrayValues ` + -TurnOffTypeChecking ` -Verbose:$verbose } | Should -Not -Throw } - It 'Should return $true' { + It 'Should return $false' { Test-DscParameterState ` -CurrentValues $currentValues ` -DesiredValues $desiredValues ` - -SortArrayValues ` - -Verbose:$verbose | Should -BeTrue + -TurnOffTypeChecking ` + -Verbose:$verbose | Should -BeFalse } } From 52136af3b53470a1ae2fef78b1100249b15fc540 Mon Sep 17 00:00:00 2001 From: Raimund Andree Date: Tue, 14 Oct 2025 09:57:50 +0200 Subject: [PATCH 8/9] Formatting --- source/Public/Compare-DscParameterState.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Public/Compare-DscParameterState.ps1 b/source/Public/Compare-DscParameterState.ps1 index 8a49961..b48e457 100644 --- a/source/Public/Compare-DscParameterState.ps1 +++ b/source/Public/Compare-DscParameterState.ps1 @@ -650,7 +650,7 @@ function Compare-DscParameterState We use .foreach() method as we are sure that $returnValue is an array. #> [Array]$returnValue = @( - $returnValue.foreach( + $returnValue.ForEach( { if ($_ -is [System.Collections.Hashtable]) { From e3414b8f34116e628016f45eceb9d40aff02363c Mon Sep 17 00:00:00 2001 From: Raimund Andree Date: Tue, 14 Oct 2025 09:58:18 +0200 Subject: [PATCH 9/9] More tests for 'Compare-DscParameterState' --- .../Compare-DscParameterState.Tests.ps1 | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/Unit/Public/Compare-DscParameterState.Tests.ps1 b/tests/Unit/Public/Compare-DscParameterState.Tests.ps1 index d347f47..2f43869 100644 --- a/tests/Unit/Public/Compare-DscParameterState.Tests.ps1 +++ b/tests/Unit/Public/Compare-DscParameterState.Tests.ps1 @@ -1258,6 +1258,7 @@ Describe 'DscResource.Common\Compare-DscParameterState' { Bool = $true Int = 99 Array = 'a', 'b', 'c', 1 + SingleValueArray = 'v1', 'v2' #for testing the comparison of single value arrays in the desired state Hashtable = @{ k1 = 'Test' k2 = 123 @@ -1514,6 +1515,41 @@ Describe 'DscResource.Common\Compare-DscParameterState' { } } + Context 'When there is a single-valued array and TurnOffTypeChecking is used' { + BeforeAll { + $desiredValues = [PSObject] @{ + String = 'a string' + Bool = $true + Int = 99 + Array = 'a', 'b', 'c', 1 + SingleValueArray = 'v1' #for testing the comparison of single value arrays in the desired state + Hashtable = @{ + k1 = 'Test' + k2 = 123 + k3 = 'v1', 'v2', 'v3' + } + } + } + + It 'Should not throw exception' { + { $script:result = Compare-DscParameterState ` + -CurrentValues $currentValues ` + -DesiredValues $desiredValues ` + -TurnOffTypeChecking ` + -Verbose:$verbose } | Should -Not -Throw + } + + It 'Should not be null' { + $script:result | Should -Not -BeNullOrEmpty + } + + It 'Should return $false for SingleValueArray InDesiredState' { + $script:result.Where({ + $_.Property -eq 'SingleValueArray' + }).InDesiredState | Should -BeFalse + } + } + Context 'When both arrays are empty' { BeforeAll { $currentValues = @{