Skip to content

Commit 164b0c9

Browse files
committed
Merge remote-tracking branch 'origin/main' into nohwnd-cascading-beforecontainer
# Conflicts: # tst/Pester.RSpec.Parallel.ts.ps1
2 parents 2ac361f + eceb07c commit 164b0c9

2 files changed

Lines changed: 69 additions & 0 deletions

File tree

src/functions/Pester.Parallel.ps1

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,24 @@ function Invoke-TestInParallel {
435435
# Keep only well-formed worker results (defensive against stray pipeline output).
436436
$results = @($results | & $SafeCommands['Where-Object'] { $_ -is [System.Management.Automation.PSCustomObject] -and $null -ne $_.PSObject.Properties['Containers'] })
437437

438+
# The filter above cannot tell stray output from a worker that died before it returned its
439+
# result object, so on its own it would drop a whole test file and let the run report success
440+
# with fewer files than it was given. Losing results silently is worse than failing, so compare
441+
# what came back against what was sent and name the files that went missing. The worker's own
442+
# error was already surfaced by Invoke-InRunspacePool, this says which file it cost us.
443+
if ($results.Count -ne $work.Count) {
444+
$returnedPaths = @{}
445+
foreach ($r in $results) {
446+
if ($null -ne $r.PSObject.Properties['Path']) { $returnedPaths[$r.Path] = $true }
447+
}
448+
449+
$missing = @(foreach ($w in $work) {
450+
if (-not $returnedPaths.ContainsKey($w.Path)) { $w.Path }
451+
})
452+
453+
throw "Parallel run lost the results of $($missing.Count) of $($work.Count) file(s), the worker(s) running them did not return a result. See the errors above for why. Lost: $($missing -join ', ')"
454+
}
455+
438456
# Restore the original discovery order so replay and the merged run are deterministic
439457
# regardless of which worker finished first.
440458
$order = @{}

tst/Pester.RSpec.Parallel.ts.ps1

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,57 @@ BeforeAll { }
644644
}
645645
}
646646

647+
b "Lost worker results" {
648+
t "fails the run instead of returning fewer files than it was given" {
649+
# A worker that dies before returning its result object leaves nothing for the
650+
# well-formed-result filter to keep, so without the count check the run would report
651+
# success for the files that did come back and never mention the one that did not.
652+
# Losing a test file silently is worse than failing, so this must throw and name it.
653+
$folder = Join-Path ([IO.Path]::GetTempPath()) ([Guid]::NewGuid().Guid)
654+
$null = New-Item -ItemType Directory -Path $folder -Force
655+
foreach ($name in 'A', 'B', 'C') {
656+
Set-Content -Path (Join-Path $folder "$name.Tests.ps1") -Value "Describe '$name' { It 'i' { 1 | Should -Be 1 } }"
657+
}
658+
659+
try {
660+
# Stand in for a worker that died: hand Invoke-TestInParallel a runspace-pool
661+
# runner that drops B's result on the floor and returns the other two.
662+
$err = & (Get-Module Pester) {
663+
param ($Root)
664+
665+
$original = ${function:Invoke-InRunspacePool}
666+
${function:Invoke-InRunspacePool} = {
667+
param ($InputObject, $ScriptBlock, $ThrottleLimit, $ItemParameterName = 'item', $Parameters = @{})
668+
foreach ($i in $InputObject) {
669+
if ($i.Path -like '*B.Tests.ps1') { continue }
670+
[PSCustomObject]@{ Path = $i.Path; Containers = @(); Tape = @(); Coverage = $null }
671+
}
672+
}
673+
674+
try {
675+
$c = [PesterConfiguration]::Default
676+
$c.Run.Path = $Root
677+
$c.Run.Parallel = $true
678+
$c.Output.Verbosity = 'None'
679+
$containers = @(Find-File -Path $Root -Extension '.Tests.ps1' | ForEach-Object { New-BlockContainerObject -File $_ })
680+
681+
try {
682+
$null = Invoke-TestInParallel -BlockContainer $containers -Configuration $c
683+
$null
684+
}
685+
catch { $_.Exception.Message }
686+
}
687+
finally { ${function:Invoke-InRunspacePool} = $original }
688+
} $folder
689+
690+
$err | Verify-NotNull
691+
$err | Verify-Like '*lost the results of 1 of 3 file(s)*'
692+
$err | Verify-Like '*B.Tests.ps1*'
693+
}
694+
finally { Remove-Item -Path $folder -Recurse -Force }
695+
}
696+
}
697+
647698
b "Invoke-InRunspacePool" {
648699
# The parallelism primitive Run.Parallel is built on. It replaces ForEach-Object -Parallel,
649700
# which does not exist on Windows PowerShell 5.1, so these run on both editions and are the

0 commit comments

Comments
 (0)