diff --git a/test/powershell/Modules/Microsoft.PowerShell.Core/Job.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Core/Job.Tests.ps1 index 8436cbd09..5c33da9f6 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Core/Job.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Core/Job.Tests.ps1 @@ -1,49 +1,141 @@ +Import-Module $PSScriptRoot\..\..\Common\Test.Helpers.psm1 Describe "Job Cmdlet Tests" -Tag "CI" { Context "Simple Jobs" { - AfterEach { - Get-Job | Remove-Job -force - } BeforeEach { - $j = start-job -scriptblock { 1 + 1 } + $j = Start-Job -ScriptBlock { 1 + 1 } -Name "My Job" + } + AfterEach { + Get-Job | Remove-Job -Force } It "Start-Job produces a job object" { - $j | Should BeOfType System.Management.Automation.Job + $j | Should BeOfType "System.Management.Automation.Job" + $j.Name | Should Be "My Job" } It "Get-Job retrieves a job object" { - (Get-Job -id $j.id) | Should BeOfType System.Management.Automation.Job + (Get-Job -Id $j.Id) | Should BeOfType "System.Management.Automation.Job" + } + It "Get-Job retrieves an array of job objects" { + Start-Job -ScriptBlock { 2 * 2 } + $jobs = Get-Job + $jobs.Count | Should Be 2 + foreach ($job in $jobs) + { + $job | Should BeOfType "System.Management.Automation.Job" + } } It "Remove-Job can remove a job" { - remove-job $j -force - try { - get-job $j -ea Stop - throw "Execution OK" - } - catch { - $_.FullyQualifiedErrorId | should be "JobWithSpecifiedNameNotFound,Microsoft.PowerShell.Commands.GetJobCommand" - } + Remove-Job $j -Force + { Get-Job $j -ErrorAction Stop } | ShouldBeErrorId "JobWithSpecifiedNameNotFound,Microsoft.PowerShell.Commands.GetJobCommand" } - It "Receive-Job can retrieve job results" -pending { - $waitjob = Wait-Job -Timeout 10 -id $j.id - if ( $waitJob ) { - $result = receive-job -id $j.id - $result.id | Should be 2 - } + It "Receive-Job can retrieve job results" { + Wait-Job -Timeout 60 -id $j.id | Should Not BeNullOrEmpty + receive-job -id $j.id | Should be 2 + } + } + Context "Jobs with arguments" { + It "Start-Job accepts arguments" { + $sb = { Write-Output $args[1]; Write-Output $args[0] } + $j = Start-Job -ScriptBlock $sb -ArgumentList "$TestDrive", 42 + Wait-job -Timeout (5 * 60) $j | Should Be $j + $r = Receive-Job $j + $r -Join "," | Should Be "42,$TestDrive" } } Context "jobs which take time" { BeforeEach { - $j = start-job -scriptblock { Start-Sleep 15 } + $j = Start-Job -ScriptBlock { Start-Sleep 15 } } AfterEach { - Get-Job | Remove-Job -force + Get-Job | Remove-Job -Force } It "Wait-Job will wait for a job" { - $result = wait-Job $j - $result | should be $j + $result = Wait-Job $j + $result | Should Be $j + $j.State | Should Be "Completed" } - It "Stop-Job will stop a job" -pending { - Stop-Job -id $j.id - $j.Status |Should be Stopped + It "Wait-Job will timeout waiting for a job" { + $result = Wait-Job -Timeout 2 $j + $result | Should Be $null + } + It "Stop-Job will stop a job" { + Stop-Job -Id $j.Id + $j.State | Should Be "Stopped" + } + It "Remove-Job will not remove a running job" { + $id = $j.Id + Remove-Job $j -ErrorAction SilentlyContinue + $job = Get-Job -Id $id + $job | Should Be $j + } + It "Remove-Job -Force will remove a running job" { + $id = $j.Id + Remove-Job $j -Force + $job = Get-Job -Id $id -ErrorAction SilentlyContinue + $job | Should Be $null + } + } + Context "Retrieving partial output from jobs" { + BeforeAll { + function GetResults($job, $n, $keep) + { + $results = @() + + # $count allows us to bail out after 5 minutes, avoiding an endless loop + for ($count = 0; $results.Count -lt $n; $count++) + { + if ($count -eq 1000) + { + # It's been 5 minutes and we still have collected enough results! + throw "Receive-Job behaves suspiciously: Cannot receive $n results in 5 minutes." + } + + # sleep for 300 ms to allow data to be produced + Start-Sleep -Milliseconds 300 + + if ($keep) + { + $results = Receive-Job -Keep $job + } + else + { + $results += Receive-Job $job + } + } + + return $results + } + + function CheckContent($array) + { + for ($i=1; $i -lt $array.Count; $i++) + { + if ($array[$i] -ne ($array[$i-1] + 1)) + { + return $false + } + } + + return $true + } + + } + BeforeEach { + $j = Start-Job -ScriptBlock { $count = 1; while ($true) { Write-Output ($count++); Start-Sleep -Milliseconds 30 } } + } + AfterEach { + Get-Job | Remove-Job -Force + } + + It "Receive-Job will retrieve partial output" { + $result1 = GetResults $j 5 $false + $result2 = GetResults $j 5 $false + CheckContent ($result1 + $result2) | Should Be $true + } + It "Receive-Job will retrieve partial output, including -Keep results" { + $result1 = GetResults $j 5 $true + $result2 = GetResults $j ($result1.Count + 5) $false + Compare-Object -SyncWindow 0 -PassThru $result1 $result2[0..($result1.Count-1)] | Should Be $null + $result2[$result1.Count - 1] + 1 | Should Be $result2[$result1.Count] } } } @@ -66,10 +158,10 @@ Describe "Debug-job test" -tag "Feature" { $ps.AddScript('$job = start-job { 1..300 | % { sleep 1 } }').Invoke() $ps.Commands.Clear() $ps.Runspace.Debugger.GetCallStack() | Should BeNullOrEmpty - start-sleep 3 + Start-Sleep 3 $asyncResult = $ps.AddScript('debug-job $job').BeginInvoke() $ps.commands.clear() - start-sleep 2 + Start-Sleep 2 $result = $ps.runspace.Debugger.GetCallStack() $result.Command | Should be "" }