ps/Modules/Alkami.PowerShell.Common/Public/Invoke-Parallel2.tests.ps1

254 lines
8.6 KiB
PowerShell
Raw Normal View History

2023-05-30 22:51:22 -07:00
. $PSScriptRoot\..\..\Load-PesterModules.ps1
$here = Split-Path -Parent $MyInvocation.MyCommand.Path
$sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.tests\.', '.'
$functionPath = Join-Path -Path $here -ChildPath $sut
Write-Host "Overriding SUT: $functionPath"
Import-Module $functionPath -Force
$moduleForMock = ""
Describe 'Invoke-Parallel2' {
Context 'Ensure Correctness - Batched Parallelism' {
It 'Returns Correct Results' {
$numbers = 1..50
$results = Invoke-Parallel2 -objects $numbers -script {
param($number)
return $number
}
# Make sure it has the right number of results.
$results.Count | Should -Be 50
# Make sure it returned all of the right results.
# The sum of 1-50 is 1275
$sum = 0
foreach($result in $results.Result) {
$sum += $result
}
$sum | Should -Be 1275
}
It 'Handles Zero Items' {
$numbers = $null
$results = Invoke-Parallel2 -objects $numbers -script {
param($number)
return $number
}
$results | Should -Be $null
}
It 'Handles One Item' {
$numbers = @(1)
$results = Invoke-Parallel2 -objects $numbers -script {
param($number)
return $number
}
$results.Result | Should -Be 1
}
It 'Handles ThreadCount -gt NumObjects' {
$numbers = 1..8
$numThreads = 400
$results = Invoke-Parallel2 -objects $numbers -numThreads $numThreads -script {
param($number)
return $number
}
$results.Count | Should -Be 8
}
It 'Handles Odd Thread Division' {
$numbers = 1..8
$numThreads = 3
$results = Invoke-Parallel2 -objects $numbers -numThreads $numThreads -script {
param($number)
return $number
}
$results.Count | Should -Be 8
}
It 'Handles Jobless Last Thread' {
# This is an edge case where Ceil(21 items / 8 threads) is rounded up to 3 items per thread.
# 7*3 == 21, which means the last thread at 8 threads doesn't have any work to do.
# There isn't a more fair way to divy up the work between the threads.
# Arbitrarily giving the 8th thread work from the 7th thread won't help in theory.
$numbers = @(1..21)
$numThreads = 8
$results = Invoke-Parallel2 -objects $numbers -numThreads $numThreads -script {
param($number)
return $number
}
$results.Count | Should -Be 21
}
}
Context 'Ensure Correctness - Thread Per Object Parallelism' {
It 'Returns Correct Results' {
$numbers = 1..6
$results = Invoke-Parallel2 -objects $numbers -threadPerObject -script {
param($number)
return $number
}
# Make sure it has the right number of results.
$results.Count | Should -Be 6
# Make sure it returned all of the right results.
# The sum of 1-6 is 21
$sum = 0
foreach($result in $results.Result) {
$sum += $result
}
$sum | Should -Be 21
}
It 'Handles Zero Items' {
$numbers = $null
$results = Invoke-Parallel2 -objects $numbers -threadPerObject -script {
param($number)
return $number
}
$results | Should -Be $null
}
It 'Handles One Item' {
$numbers = @(1)
$results = Invoke-Parallel2 -objects $numbers -threadPerObject -script {
param($number)
return $number
}
$results.Result | Should -Be 1
}
It 'Handles ThreadCount -gt NumObjects' {
$numbers = 1..8
$numThreads = 400
$results = Invoke-Parallel2 -objects $numbers -numThreads $numThreads -threadPerObject -script {
param($number)
return $number
}
$results.Count | Should -Be 8
}
}
Context 'Ensure Correctness - Thread Per Object Error Handling' {
It 'Returns Error Results' {
$numbers = 1..4
$results = Invoke-Parallel2 -objects $numbers -threadPerObject -ErrorAction SilentlyContinue -script {
param($number)
throw "Failure!"
}
# All of the results should fail, and contain the correct error.
$badResults = $results | Where-Object { $_.Success -eq $false }
$badResults.Count | Should -Be 4
for($i = 0; $i -lt 4; $i++) {
$badResults[$i].Error | Should -Be "Failure!"
}
}
It 'Returns All Results When ContinueOnFailure is True' {
$numbers = 1..4
$results = Invoke-Parallel2 -objects $numbers -threadPerObject -numThreads 1 -ErrorAction SilentlyContinue -script {
param($number)
throw "Failure!"
}
# All of the results should fail, and contain the correct error.
$badResults = $results | Where-Object { $_.Success -eq $false }
$badResults.Count | Should -Be 4
for($i = 0; $i -lt 4; $i++) {
$badResults[$i].Error | Should -Be "Failure!"
}
}
It 'Returns One Result With StopProcessingJobsOnError' {
$numbers = 1..4
$results = Invoke-Parallel2 -objects $numbers -threadPerObject -numThreads 1 -ErrorAction SilentlyContinue -StopProcessingJobsOnError -script {
param($number)
throw "Failure!"
}
# Only one result should be returned because we are at a parallelism of 1, and we are -not- continuing on error.
[array]$badResults = $results | Where-Object { $_.Success -eq $false }
$badResults.Count | Should -Be 1
$badResults.Error | Should -Be "Failure!"
}
It 'Returns Outstanding Thread Results and Doesnt Create More' {
$numbers = 1..6
$results = Invoke-Parallel2 -objects $numbers -threadPerObject -numThreads 3 -ErrorAction SilentlyContinue -StopProcessingJobsOnError -script {
param($number)
if($number -eq 1) {
throw "Failure!"
} else {
# Make sure the other non-failing results take a little time, so that more jobs are not spawned.
Start-Sleep -Seconds 2
}
}
[array]$goodResults = $results | Where-Object { $_.Success -eq $true }
[array]$badResults = $results | Where-Object { $_.Success -eq $false }
# We should have 3 results.
# .. because we are at a parallelism of 3 jobs (out of 6 objects)
# .. and one of them fails. Two should succeed, one should fail, and we should not create any more jobs.
$results.Count | Should -Be 3
$goodResults.Count | Should -Be 2
$badResults.Count | Should -Be 1
}
}
Context 'Ensure Correctness - Batched Error Handling' {
It 'Returns Success Results' {
$numbers = 1..4
$results = Invoke-Parallel2 -objects $numbers -ErrorAction SilentlyContinue -script {
param($number)
# Do nothing. All good.
}
# All of the results should fail, and contain the correct error.
$goodResults = $results | Where-Object { $_.Success -eq $true }
$goodResults.Count | Should -Be 4
for($i = 0; $i -lt 4; $i++) {
$goodResults[$i].Error | Should -Be $null
}
}
It 'Returns All Results When There is Failure' {
$numbers = 1..4
$results = Invoke-Parallel2 -objects $numbers -numThreads 1 -ErrorAction SilentlyContinue -script {
param($number)
throw "Failure!"
}
# All of the results should fail, and contain the correct error.
$badResults = $results | Where-Object { $_.Success -eq $false }
$badResults.Count | Should -Be 4
for($i = 0; $i -lt 4; $i++) {
$badResults[$i].Error | Should -Be "Failure!"
}
}
}
}