Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Moved StrictOrder, PowerShell 7.0.0-preview.2 DBNull support and StrictEquality #45

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Format/src/Format.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ function Format-Dictionary ($Value) {
}

function Format-Nicely ($Value, [switch]$Pretty) {
if ($null -eq $Value)
if (Is-Null -Value $Value)
{
return Format-Null -Value $Value
}
Expand Down
6 changes: 6 additions & 0 deletions TypeClass/src/TypeClass.psm1
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
function Is-Null ($Value) {
# Since PowerShell 7.0 [DBNull] -eq $null.
$null -eq $Value -or $Value -is [DBNull] -or $Value.Psobject.TypeNames[0] -like '*System.DBNull'
}

function Is-Value ($Value) {
$Value = $($Value)
$Value -is [ValueType] -or $Value -is [string] -or $value -is [scriptblock]
Expand Down Expand Up @@ -50,6 +55,7 @@ function Is-DataRow ($Value) {
}

Export-ModuleMember -Function @(
'Is-Null'
'Is-Value'
'Is-Collection'
'Is-DataTable'
Expand Down
86 changes: 66 additions & 20 deletions src/Equivalence/Assert-Equivalent.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ function Get-ValueNotEquivalentMessage ($Expected, $Actual, $Property, $Options)
$Expected = Format-Nicely -Value $Expected
$Actual = Format-Nicely -Value $Actual
$propertyInfo = if ($Property) { " property $Property with value" }
$comparison = if ("Equality" -eq $Options.Comparator) { 'equal' } else { 'equivalent' }
$comparison = if ("Equality" -eq $Options.Comparator) { 'equal' }
elseif ("StrictEquality" -eq $Options.Comparator) { 'strictly equal' } else { 'equivalent' }
"Expected$propertyInfo '$Expected' to be $comparison to the actual value, but got '$Actual'."
}

Expand Down Expand Up @@ -81,7 +82,7 @@ function Compare-CollectionEquivalent ($Expected, $Actual, $Property, $Options)
v "`nSearching for `$Expected[$e]:"
$currentExpected = $Expected[$e]
$found = $false
if ($StrictOrder) {
if ($Options.StrictOrder) {
$currentActual = $Actual[$e]
if ($taken -notcontains $e -and (-not (Compare-Equivalent -Expected $currentExpected -Actual $currentActual -Path $Property -Options $Options)))
{
Expand Down Expand Up @@ -161,7 +162,7 @@ function Compare-DataTableEquivalent ($Expected, $Actual, $Property, $Options) {
for ($e = 0; $e -lt $eEnd; $e++) {
$currentExpected = $Expected.Rows[$e]
$found = $false
if ($StrictOrder) {
if ($Options.StrictOrder) {
$currentActual = $Actual.Rows[$e]
if ((-not (Compare-Equivalent -Expected $currentExpected -Actual $currentActual -Path $Property -Options $Options)) -and $taken -notcontains $e) {
$taken += $e
Expand Down Expand Up @@ -191,6 +192,48 @@ function Compare-DataTableEquivalent ($Expected, $Actual, $Property, $Options) {
}
}

function Compare-NullEquivalent ($Actual, $Expected, $Property, $Options) {
if ("Equivalency" -eq $Options.Comparator) {
v "Equivalency comparator is used, values will be compared for equivalency."
if (Is-Null -Value $Actual)
{
v -Equivalence "`$Actual is equivalent to `$null."
return
}
}
elseif ("StrictEquality" -eq $Options.Comparator)
{
v "StrictEquality comparator is used, values will be compared for equality."
if ($Expected -isnot [Object] -and $Actual -isnot [Object])
{
v -Equivalence "`$Actual is equal to `$null, because it is `$null."
return
}
if ($Expected -is [Object] -and $Actual -is [Object] -and
$Expected.Psobject.TypeNames[0] -like '*System.DBNull' -and
$Actual.Psobject.TypeNames[0] -like '*System.DBNull')
{
v -Equivalence "`$Actual is equal to DBNull, because it is DBNull."
return
}
}
else
{
v "Equality comparator is used, values will be compared for equality."
if ($Expected -is [Object] -and $Expected.Psobject.TypeNames[0] -like '*System.DBNull') {$Expected = [DBNull]::Value}
if ($Actual -is [Object] -and $Actual.Psobject.TypeNames[0] -like '*System.DBNull') {$Actual = [DBNull]::Value}
if ($Expected -eq $Actual)
{
v -Equivalence "`$Actual is equal to DBNull, because it is DBNull."
return
}
}
# we terminate here, either we passed the test and return nothing, or we did not
# and return message here
v -Difference "`$Actual is not equivalent to $(Format-Nicely $Expected)."
return Get-ValueNotEquivalentMessage -Expected $Expected -Actual $Actual -Property $Property -Options $Options
}

function Compare-ValueEquivalent ($Actual, $Expected, $Property, $Options) {
$Expected = $($Expected)
if (-not (Is-Value -Value $Expected))
Expand Down Expand Up @@ -248,6 +291,16 @@ function Compare-ValueEquivalent ($Actual, $Expected, $Property, $Options) {
return
}
}
elseif ("StrictEquality" -eq $Options.Comparator)
{
v "StrictEquality comparator is used, values will be compared for strict equality."
if ($Expected.GetType() -ne $Actual.GetType())
{
v -Difference "`$Actual is not equivalent to `$Expected because their type differ."
return Get-ValueNotEquivalentMessage -Expected $Expected -Actual $Actual -Property $Path -Options $Options
}
v "types are matching, will be tested for values."
}
else
{
v "Equality comparator is used, values will be compared for equality."
Expand Down Expand Up @@ -575,21 +628,13 @@ function Compare-Equivalent {

#start by null checks to avoid implementing null handling
#logic in the functions that follow
if ($null -eq $Expected)
{
if (Is-Null -Value $Expected) {
v "`$Expected is `$null, so we are expecting `$null."
if ($Expected -ne $Actual)
{
v -Difference "`$Actual is not equivalent to $(Format-Nicely $Expected), because it has a value of type $(Format-Nicely $Actual.GetType())."
return Get-ValueNotEquivalentMessage -Expected $Expected -Actual $Actual -Property $Path -Options $Options
}
# we terminate here, either we passed the test and return nothing, or we did not
# and the previous statement returned message
v -Equivalence "`$Actual is equivalent to `$null, because it is `$null."
Compare-NullEquivalent -Expected $Expected -Actual $Actual -Property $Path -Options $Options
return
}

if ($null -eq $Actual)
if (Is-Null -Value $Actual)
{
v -Difference "`$Actual is $(Format-Nicely), but `$Expected has value of type $(Format-Nicely Get-Type $Expected), so they are not equivalent."
return Get-ValueNotEquivalentMessage -Expected $Expected -Actual $Actual -Property $Path
Expand Down Expand Up @@ -660,8 +705,7 @@ function Assert-Equivalent {
param(
$Actual,
$Expected,
$Options = (Get-EquivalencyOption),
[Switch] $StrictOrder
$Options = (Get-EquivalencyOption)
)

$areDifferent = Compare-Equivalent -Actual $Actual -Expected $Expected -Options $Options | Out-String
Expand All @@ -681,14 +725,16 @@ function Get-EquivalencyOption {
param(
[string[]] $ExcludePath = @(),
[switch] $ExcludePathsNotOnExpected,
[ValidateSet('Equivalency', 'Equality')]
[string] $Comparator = 'Equivalency'
[ValidateSet('Equivalency', 'Equality', 'StrictEquality')]
[string] $Comparator = 'Equivalency',
[switch] $StrictOrder
)

[PSCustomObject]@{
ExcludedPaths = [string[]] $ExcludePath
ExcludedPaths = [string[]] $ExcludePath
ExcludePathsNotOnExpected = [bool] $ExcludePathsNotOnExpected
Comparator = [string] $Comparator
Comparator = [string] $Comparator
StrictOrder = [bool] $StrictOrder
}
}

Expand Down
24 changes: 23 additions & 1 deletion tst/Equivalence/Assert-Equivalent.Options.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -356,8 +356,30 @@
$options = Get-EquivalencyOption -Comparator Equality
{ Assert-Equivalent -Actual $actual -Expected $expected -Options $options } | Verify-AssertionFailed
}
}

$OptionsEquality = Get-EquivalencyOption -Comparator Equality
$OptionsStrictEquality = Get-EquivalencyOption -Comparator StrictEquality
$DBNull = [DBNull]::Value
It "Test <Actual> vs <Expected> with -Comparator 'Equivalency', 'Equality', 'StrictEquality'" -TestCases @(
@{ Actual = 'False' ; Expected = $false }
@{ Actual = $null; Expected = $DBNull }
@{ Actual = 5; Expected = '5' }
@{ Actual = { 'String' }; Expected = { 'String' } }
) {
param($Expected, $Actual)
# Equivalent
Assert-Equivalent -Actual $Actual -Expected $Expected
Assert-Equivalent -Actual $Expected -Expected $Actual
# StrictEquality
{ Assert-Equivalent -Actual $Actual -Expected $Expected -Options $OptionsStrictEquality } | Verify-AssertionFailed
{ Assert-Equivalent -Actual $Expected -Expected $Actual -Options $OptionsStrictEquality } | Verify-AssertionFailed
# Equality
$AssertResult = try { Assert-Equivalent -Actual $Actual -Expected $Expected -Options $OptionsEquality ; $true} catch {$false}
$AssertResult -eq ($Expected -eq $Actual) | Verify-True
$AssertResult = try { Assert-Equivalent -Actual $Expected -Expected $Actual -Options $OptionsEquality ; $true} catch {$false}
$AssertResult -eq ($Actual -eq $Expected) | Verify-True
}
}

Describe "Printing Options into difference report" {

Expand Down
19 changes: 2 additions & 17 deletions tst/Equivalence/Assert-Equivalent.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -440,30 +440,15 @@ InModuleScope -ModuleName Assert {
Assert-Equivalent -Actual $Actual -Expected $Expected

function SerializeDeserialize ($InputObject) {
# psv2 compatibility
# $ExpectedDeserialized = [System.Management.Automation.PSSerializer]::Deserialize([System.Management.Automation.PSSerializer]::Serialize($Expected))
# Alternatively this could be done in memory via https://github.com/Jaykul/Reflection/blob/master/CliXml.psm1, but I don't want to fiddle with more
# relfection right now
try {
$path = [IO.Path]::GetTempFileName()

Export-Clixml -Path $path -InputObject $InputObject -Force | Out-Null
Import-Clixml -Path $path
}
finally {
if ($null -ne $path -and (Test-Path $path)) {
Remove-Item -Path $path -Force
}
}
, [System.Management.Automation.PSSerializer]::Deserialize([System.Management.Automation.PSSerializer]::Serialize($InputObject, 3))
}


$ExpectedDeserialized = SerializeDeserialize $Expected
$ActualDeserialized = SerializeDeserialize $Actual
Assert-Equivalent -Actual $ActualDeserialized -Expected $ExpectedDeserialized
Assert-Equivalent -Actual $Actual -Expected $ExpectedDeserialized

{Assert-Equivalent -Actual $Actual -Expected $Expected -StrictOrder} | Should -Throw
{Assert-Equivalent -Actual $Actual -Expected $Expected -Options (Get-EquivalencyOption -StrictOrder)} | Should -Throw

$Actual.Rows[1].Name = 'D'
{Assert-Equivalent -Actual $Actual -Expected $Expected} | Should -Throw
Expand Down