diff --git a/Functions/Assertions/Be.Tests.ps1 b/Functions/Assertions/Be.Tests.ps1 index 262e880e2..0a3bf7882 100644 --- a/Functions/Assertions/Be.Tests.ps1 +++ b/Functions/Assertions/Be.Tests.ps1 @@ -85,11 +85,19 @@ InModuleScope Pester { {abc} | Should -CEQ "abc" } - It 'Does not overflow on IEnumerable' { + It 'Does not overflow on cyclic object graph' { # see https://github.com/pester/Pester/issues/785 $doc = [xml]'' $doc | Should be $doc } + + Context 'recursion limit' { + Mock IsIList { $true } + It 'throws exception when self-imposed recursion limit is reached' { + $doc = [xml]'' + { $doc | Should be $doc } | Should throw 'reached recursion depth limit' + } + } } Describe "PesterBeFailureMessage" { diff --git a/Functions/Assertions/Be.ps1 b/Functions/Assertions/Be.ps1 index 7b08022e2..fbb17d4f8 100644 --- a/Functions/Assertions/Be.ps1 +++ b/Functions/Assertions/Be.ps1 @@ -178,8 +178,14 @@ function ArraysAreEqual param ( [object[]] $First, [object[]] $Second, - [switch] $CaseSensitive + [switch] $CaseSensitive, + [int] $RecursionLimit = 100 ) + $recursionDepth++ + if ( $recursionDepth -gt $RecursionLimit ) + { + throw "reached recursion depth limit of $RecursionLimit when comparing arrays $First and $Second" + } # Do not remove the subexpression @() operators in the following two lines; doing so can cause a # silly error in PowerShell v3. (Null Reference exception from the PowerShell engine in a @@ -196,7 +202,7 @@ function ArraysAreEqual for ($i = 0; $i -lt $First.Count; $i++) { - if ((IsCollection $First[$i]) -or (IsCollection $Second[$i])) + if ((IsIList $First[$i]) -or (IsIList $Second[$i])) { if (-not (ArraysAreEqual -First $First[$i] -Second $Second[$i] -CaseSensitive:$CaseSensitive)) { @@ -231,11 +237,11 @@ function ArrayOrSingleElementIsNullOrEmpty return $null -eq $Array -or $Array.Count -eq 0 -or ($Array.Count -eq 1 -and $null -eq $Array[0]) } -function IsCollection +function IsIList { param ([object] $InputObject) - return $InputObject -is [Array] + return [bool]$InputObject.GetType().GetInterface('IList') } function ReplaceValueInArray