MegaBites-AI/Windows-powershell
0372
1# Copyright (c) Microsoft Corporation.2# Licensed under the MIT License.3Describe "Job Cmdlet Tests" -Tag "CI" {4 Context "Simple Jobs" {5 BeforeEach {6 $j = Start-Job -ScriptBlock { 1 + 1 } -Name "My Job"7 }8 AfterEach {9 Get-Job | Remove-Job -Force10 }11 It "Start-Job produces a job object" {12 $j | Should -BeOfType System.Management.Automation.Job13 $j.Name | Should -BeExactly "My Job"14 }15 It "Get-Job retrieves a job object" {16 (Get-Job -Id $j.Id) | Should -BeOfType System.Management.Automation.Job17 }18 It "Get-Job retrieves an array of job objects" {19 Start-Job -ScriptBlock { 2 * 2 }20 $jobs = Get-Job21 $jobs.Count | Should -Be 222 foreach ($job in $jobs)23 {24 $job | Should -BeOfType System.Management.Automation.Job25 }26 }27 It "Remove-Job can remove a job" {28 Remove-Job $j -Force29 { Get-Job $j -ErrorAction Stop } | Should -Throw -ErrorId "JobWithSpecifiedNameNotFound,Microsoft.PowerShell.Commands.GetJobCommand"30 }31 It "Receive-Job can retrieve job results" {32 Wait-Job -Timeout 60 -Id $j.id | Should -Not -BeNullOrEmpty33 Receive-Job -Id $j.id | Should -Be 234 }35 It "-RunAs32 not supported from 64-bit pwsh" -Skip:(-not [System.Environment]::Is64BitProcess) {36 { Start-Job -ScriptBlock {} -RunAs32 } | Should -Throw -ErrorId "RunAs32NotSupported,Microsoft.PowerShell.Commands.StartJobCommand"37 }38 It "-RunAs32 supported in 32-bit pwsh" -Skip:([System.Environment]::Is64BitProcess) {39 $job = Start-Job -ScriptBlock { 1+1 } -RunAs3240 Receive-Job $job -Wait | Should -Be 241 }42 }43 Context "Jobs with arguments" {44 It "Start-Job accepts arguments" {45 $sb = { Write-Output $args[1]; Write-Output $args[0] }46 $j = Start-Job -ScriptBlock $sb -ArgumentList "$TestDrive", 4247 Wait-Job -Timeout (5 * 60) $j | Should -Be $j48 $r = Receive-Job $j49 $r -Join "," | Should -Be "42,$TestDrive"50 }51 }52 Context "jobs which take time" {53 BeforeEach {54 $j = Start-Job -ScriptBlock { Start-Sleep -Seconds 8 }55 }56 AfterEach {57 Get-Job | Remove-Job -Force58 }59 It "Wait-Job will wait for a job" {60 $result = Wait-Job $j61 $result | Should -Be $j62 $j.State | Should -BeExactly "Completed"63 }64 It "Wait-Job will timeout waiting for a job" {65 $result = Wait-Job -Timeout 2 $j66 $result | Should -BeNullOrEmpty67 }68 It "Stop-Job will stop a job" {69 Stop-Job -Id $j.Id70 $out = Receive-Job $j -ErrorVariable err71 $out | Should -BeNullOrEmpty72 $err | Should -BeNullOrEmpty73 $j.State | Should -BeExactly "Stopped"74 }75 It "Remove-Job will not remove a running job" {76 $id = $j.Id77 Remove-Job $j -ErrorAction SilentlyContinue78 $job = Get-Job -Id $id79 $job | Should -Be $j80 }81 It "Remove-Job -Force will remove a running job" {82 $id = $j.Id83 Remove-Job $j -Force84 $job = Get-Job -Id $id -ErrorAction SilentlyContinue85 $job | Should -BeNullOrEmpty86 }87 }88 Context "Retrieving partial output from jobs" {89 BeforeAll {90 function GetResults($job, $n, $keep)91 {92 $results = @()93 94 # $count allows us to bail out after 5 minutes, avoiding an endless loop95 for ($count = 0; $results.Count -lt $n; $count++)96 {97 if ($count -eq 1000)98 {99 # It's been 5 minutes and we still have collected enough results!100 throw "Receive-Job behaves suspiciously: Cannot receive $n results in 5 minutes."101 }102 103 # Wait to allow data to be produced104 Start-Sleep -Milliseconds 300105 106 if ($keep)107 {108 $results = Receive-Job -Keep $job109 }110 else111 {112 $results += Receive-Job $job113 }114 }115 116 return $results117 }118 119 function CheckContent($array)120 {121 for ($i=1; $i -lt $array.Count; $i++)122 {123 if ($array[$i] -ne ($array[$i-1] + 1))124 {125 return $false126 }127 }128 129 return $true130 }131 132 }133 BeforeEach {134 $j = Start-Job -ScriptBlock { $count = 1; while ($true) { Write-Output ($count++); Start-Sleep -Milliseconds 30 } }135 }136 AfterEach {137 Get-Job | Remove-Job -Force138 }139 140 It "Receive-Job will retrieve partial output" {141 $result1 = GetResults $j 5 $false142 $result2 = GetResults $j 5 $false143 CheckContent ($result1 + $result2) | Should -BeTrue144 }145 It "Receive-Job will retrieve partial output, including -Keep results" {146 $result1 = GetResults $j 5 $true147 $result2 = GetResults $j ($result1.Count + 5) $false148 Compare-Object -SyncWindow 0 -PassThru $result1 $result2[0..($result1.Count-1)] | Should -BeNullOrEmpty149 $result2[$result1.Count - 1] + 1 | Should -Be $result2[$result1.Count]150 }151 }152}153Describe "Debug-job test" -Tag "Feature" {154 BeforeAll {155 $rs = [runspacefactory]::CreateRunspace()156 $rs.Open()157 $rs.Debugger.SetDebugMode([System.Management.Automation.DebugModes]::RemoteScript)158 $rs.Debugger.add_DebuggerStop({$true})159 $ps = [powershell]::Create()160 $ps.Runspace = $rs161 }162 AfterAll {163 $rs.Dispose()164 $ps.Dispose()165 }166 # we check this via implication.167 # if we're debugging a job, then the debugger will have a callstack168 It "Debug-Job will break into debugger" -Pending {169 $ps.AddScript('$job = start-job { 1..300 | ForEach-Object { Start-Sleep 1 } }').Invoke()170 $ps.Commands.Clear()171 $ps.Runspace.Debugger.GetCallStack() | Should -BeNullOrEmpty172 Start-Sleep 3173 $asyncResult = $ps.AddScript('debug-job $job').BeginInvoke()174 $ps.commands.clear()175 Start-Sleep 2176 $result = $ps.runspace.Debugger.GetCallStack()177 $result.Command | Should -BeExactly "<ScriptBlock>"178 }179}180 181Describe "Ampersand background test" -Tag "CI", "Slow" {182 Context "Simple background job" {183 AfterEach {184 Get-Job | Remove-Job -Force185 }186 It "Background with & produces a job object" {187 $j = Write-Output Hi &188 $j | Should -BeOfType System.Management.Automation.Job189 }190 }191 Context "Variable tests" {192 AfterEach {193 Get-Job | Remove-Job -Force194 }195 It "doesn't cause error when variable is missing" {196 Remove-Item variable:name -ErrorAction Ignore197 $j = Write-Output "Hi $name" &198 Receive-Job $j -Wait | Should -BeExactly "Hi "199 }200 It "Copies variables to the child process" {201 $n1 = "Bob"202 $n2 = "Mary"203 ${n 3} = "Bill"204 $j = Write-Output "Hi $n1! Hi ${n2}! Hi ${n 3}!" &205 Receive-Job $j -Wait | Should -BeExactly "Hi Bob! Hi Mary! Hi Bill!"206 }207 It 'Make sure that $PID from the parent process does not overwrite $PID in the child process' {208 $j = Write-Output $PID &209 $cpid = Receive-Job $j -Wait210 $PID | Should -Not -BeExactly $cpid211 }212 It 'Make sure that $global:PID from the parent process does not overwrite $global:PID in the child process' {213 $j = Write-Output $global:pid &214 $cpid = Receive-Job -Wait $j215 $PID | Should -Not -BeExactly $cpid216 }217 It "starts in the current directory" {218 $j = Get-Location | ForEach-Object -MemberName Path &219 Receive-Job -Wait $j | Should -Be ($PWD.Path)220 }221 It "Make sure Set-Location is not used in the job's script block to set the working directory" {222 $j = (Get-Variable -Value ExecutionContext).SessionState.PSVariable.Get("MyInvocation").Value.MyCommand.ScriptBlock & 223 (Receive-Job -Wait $j).ToString() | Should -BeExactly "(Get-Variable -Value ExecutionContext).SessionState.PSVariable.Get(`"MyInvocation`").Value.MyCommand.ScriptBlock"224 }225 It "Test that changing working directory also changes background job's working directory" {226 Set-Location ..227 $WorkingDirectory = (Get-Location).ToString()228 $BackgroundJob = (Get-Location &) 229 (Receive-Job -Wait $BackgroundJob).ToString() | Should -BeExactly $WorkingDirectory230 }231 It "Test that output redirection is done in the background job" {232 $j = Write-Output hello > $TESTDRIVE/hello.txt &233 Receive-Job -Wait $j | Should -BeNullOrEmpty234 Get-Content $TESTDRIVE/hello.txt | Should -BeExactly "hello"235 }236 It "Test that error redirection is done in the background job" {237 $j = Write-Error MyError 2> $TESTDRIVE/myerror.txt &238 Receive-Job -Wait $j | Should -BeNullOrEmpty239 Get-Content -Raw $TESTDRIVE/myerror.txt | Should -Match "MyError"240 }241 }242 Context "Backgrounding expressions" {243 AfterEach {244 Get-Job | Remove-Job -Force245 }246 It "handles backgrounding expressions" {247 $j = 2+3 &248 Receive-Job $j -Wait | Should -Be 5249 }250 It "handles backgrounding mixed expressions" {251 $j = 1..10 | ForEach-Object -Begin {$s=0} -Process {$s += $_} -End {$s} &252 Receive-Job -Wait $j | Should -Be 55253 }254 }255}256 257Describe "Start-Job with -PSVersion parameter" -Tag "CI" {258 259 It "Verifies that -PSVersion is not supported except for version 5.1" {260 { Start-Job -PSVersion 2.0 } | Should -Throw -ErrorId 'ParameterBindingFailed,Microsoft.PowerShell.Commands.StartJobCommand'261 }262 263 It "Verifies that -PSVersion 5.1 runs the job in a version 5.1 PowerShell session" -Skip:(-not $IsWindows) {264 $version = Start-Job -PSVersion 5.1 -ScriptBlock { $PSVersionTable } | Receive-Job -Wait -AutoRemoveJob265 $version.PSVersion.Major | Should -Be 5266 $version.PSVersion.Minor | Should -Be 1267 }268}269 