Skip to content

Commit 1e271ea

Browse files
adityapatwardhanTravisEz13
authored andcommitted
Add Remoting and Job tests (PowerShell#4928)
1 parent d73e974 commit 1e271ea

File tree

6 files changed

+594
-58
lines changed

6 files changed

+594
-58
lines changed

src/System.Management.Automation/engine/remoting/commands/InvokeCommandCommand.cs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -785,13 +785,6 @@ protected override void BeginProcessing()
785785
throw new InvalidOperationException(RemotingErrorIdStrings.AsJobAndDisconnectedError);
786786
}
787787

788-
if (this.InvokeAndDisconnect &&
789-
(this.ComputerName == null || this.ComputerName.Length == 0) &&
790-
(this.ConnectionUri == null || this.ConnectionUri.Length == 0))
791-
{
792-
throw new InvalidOperationException(RemotingErrorIdStrings.InvokeDisconnectedWithoutComputerName);
793-
}
794-
795788
if (MyInvocation.BoundParameters.ContainsKey("SessionName") && !this.InvokeAndDisconnect)
796789
{
797790
throw new InvalidOperationException(RemotingErrorIdStrings.SessionNameWithoutInvokeDisconnected);

src/System.Management.Automation/resources/RemotingErrorIdStrings.resx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -911,9 +911,6 @@ Do you want to continue?</value>
911911
<data name="JobIdentifierNull" xml:space="preserve">
912912
<value>The JobIdentifier provided must not be null. Please provide a valid JobIdentifier.</value>
913913
</data>
914-
<data name="InvokeDisconnectedWithoutComputerName" xml:space="preserve">
915-
<value>No computer names or connection Uris were specified. You must provide a computer name or connection Uri when invoking a command with the -Disconnected switch.</value>
916-
</data>
917914
<data name="JobBlockedSoWaitJobCannotContinue" xml:space="preserve">
918915
<value>The Wait-Job cmdlet cannot finish working, because one or more jobs are blocked waiting for user interaction. Process interactive job output by using the Receive-Job cmdlet, and then try again.</value>
919916
</data>
Lines changed: 270 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,285 @@
11
Describe 'Basic Job Tests' -Tags 'CI' {
2-
32
BeforeAll {
4-
$job = Start-Job {1}
3+
# Make sure we do not have any jobs running
4+
Get-Job | Remove-Job -Force
5+
$timeBeforeStartedJob = Get-Date
6+
$startedJob = Start-Job -Name 'StartedJob' -ScriptBlock { 1 + 1 } | Wait-Job
7+
$timeAfterStartedJob = Get-Date
8+
9+
function script:ValidateJobInfo($job, $state, $hasMoreData, $command)
10+
{
11+
$job.State | Should BeExactly $state
12+
$job.HasMoreData | Should Be $hasMoreData
13+
14+
if($command -ne $null)
15+
{
16+
$job.Command | Should BeExactly $command
17+
}
18+
}
519
}
620

7-
It 'Test job creation' {
8-
$job | should not be $null
21+
AfterAll {
22+
$startedJob | Remove-Job -Force -ErrorAction SilentlyContinue
923
}
1024

11-
It 'Test job State' {
12-
Wait-Job $job -Timeout 60
13-
$job.JobStateInfo.State -eq 'Completed' | should be $true
25+
Context 'Basic tests' {
26+
27+
AfterEach {
28+
Get-Job | Where-Object { $_.Id -ne $startedJob.Id } | Remove-Job -ErrorAction SilentlyContinue -Force
29+
}
30+
31+
It 'Can start, wait and receive a Job' {
32+
$job = Start-Job -ScriptBlock { 1 + 1 }
33+
$result = $job | Wait-Job | Receive-Job
34+
ValidateJobInfo -job $job -state 'Completed' -hasMoreData $false -command ' 1 + 1 '
35+
$result | Should Be 2
36+
}
37+
38+
It 'Can run nested jobs' {
39+
$job = Start-Job -ScriptBlock { Start-Job -ScriptBlock { 1 + 1 } | Wait-Job | Receive-Job }
40+
ValidateJobInfo -job $job -state 'Running' -hasMoreData $true -command ' Start-Job -ScriptBlock { 1 + 1 } | Wait-Job | Receive-Job '
41+
$result = $job | Wait-Job | Receive-Job
42+
$result | Should Be 2
43+
}
44+
45+
It 'Can get errors messages from job' {
46+
$job = Start-Job -ScriptBlock { throw 'MyError' } | Wait-Job
47+
Receive-Job -Job $job -ErrorVariable ev -ErrorAction SilentlyContinue
48+
$ev[0].Exception.Message | Should BeExactly 'MyError'
49+
}
50+
51+
It 'Can get warning messages from job' {
52+
$job = Start-Job -ScriptBlock { Write-Warning 'MyWarning' } | Wait-Job
53+
Receive-Job -Job $job -WarningVariable wv -WarningAction SilentlyContinue
54+
$wv | Should BeExactly 'MyWarning'
55+
}
56+
57+
It 'Can get verbose message from job' {
58+
$job = Start-Job -ScriptBlock { Write-Verbose -Verbose 'MyVerbose' } | Wait-Job
59+
$VerboseMsg = $job.ChildJobs[0].verbose.readall()
60+
$VerboseMsg | Should BeExactly 'MyVerbose'
61+
}
62+
63+
It 'Can get progress message from job' {
64+
$job = Start-Job -ScriptBlock { Write-Progress -Activity 1 -Status 2 } | Wait-Job
65+
$ProgressMsg = $job.ChildJobs[0].progress.readall()
66+
$ProgressMsg[0].Activity | Should BeExactly 1
67+
$ProgressMsg[0].StatusDescription | Should BeExactly 2
68+
}
69+
70+
It "Create job with native command" {
71+
try {
72+
$nativeJob = Start-job { powershell -c 1+1 }
73+
$nativeJob | Wait-Job
74+
$nativeJob.State | Should BeExactly "Completed"
75+
$nativeJob.HasMoreData | Should Be $true
76+
Receive-Job $nativeJob | Should BeExactly 2
77+
Remove-Job $nativeJob
78+
{ Get-Job $nativeJob -ErrorAction Stop } | ShouldBeErrorId "JobWithSpecifiedNameNotFound,Microsoft.PowerShell.Commands.GetJobCommand"
79+
}
80+
finally {
81+
Remove-Job $nativeJob -Force -ErrorAction SilentlyContinue
82+
}
83+
}
1484
}
1585

16-
It 'Job output test' {
17-
Receive-Job $job -wait | should be 1
86+
Context 'Wait-Job tests' {
87+
88+
BeforeAll {
89+
$waitJobTestCases = @(
90+
@{ parameters = @{ Name = $startedJob.Name } ; property = '-Name'},
91+
@{ parameters = @{ Id = $startedJob.Id } ; property = '-Id'},
92+
@{ parameters = @{ Job = $startedJob } ; property = '-Job'},
93+
@{ parameters = @{ InstanceId = $startedJob.InstanceId } ; property = '-InstanceId'},
94+
@{ parameters = @{ State = $startedJob.State } ; property = '-State'}
95+
)
96+
}
97+
98+
AfterEach {
99+
Get-Job | Where-Object { $_.Id -ne $startedJob.Id } | Remove-Job -ErrorAction SilentlyContinue -Force
100+
}
101+
102+
It 'Can wait for jobs to complete using <property>' -TestCases $waitJobTestCases {
103+
param($parameters)
104+
$job = Wait-Job @parameters
105+
ValidateJobInfo -job $job -state 'Completed' -hasMoreData $true -command ' 1 + 1 '
106+
}
107+
108+
It 'Can wait for any job to complete' {
109+
$jobs = 1..3 | ForEach-Object { $seconds = $_ ; Start-Job -ScriptBlock { Start-Sleep -Seconds $using:seconds ; $using:seconds} }
110+
$waitedJob = Wait-Job -Job $jobs -Any
111+
ValidateJobInfo -job $waitedJob -state 'Completed' -hasMoreData $true -command ' Start-Sleep -Seconds $using:seconds ; $using:seconds'
112+
$result = $waitedJob | Receive-Job
113+
## We check for $result to be less than 4 so that any of the jobs completing first will considered a success.
114+
$result | Should BeLessThan 4
115+
## Check none of the jobs threw errors.
116+
$jobs.Error | Should BeNullOrEmpty
117+
}
118+
119+
It 'Can timeout waiting for a job' {
120+
$job = Start-Job -ScriptBlock { Start-Sleep -Seconds 10 }
121+
$job | Wait-Job -TimeoutSec 1
122+
ValidateJobInfo -job $job -state 'Running' -hasMoreData $true -command ' Start-Sleep -Seconds 10 '
123+
}
18124
}
19125

20-
It "Create job with native command" {
21-
try {
22-
$nativeJob = Start-job { powershell -c 1+1 }
23-
$nativeJob | Wait-Job
24-
$nativeJob.State | Should BeExactly "Completed"
25-
$nativeJob.HasMoreData | Should Be $true
26-
Receive-Job $nativeJob | Should BeExactly 2
27-
Remove-Job $nativeJob
28-
{ Get-Job $nativeJob -ErrorAction Stop } | ShouldBeErrorId "JobWithSpecifiedNameNotFound,Microsoft.PowerShell.Commands.GetJobCommand"
126+
Context 'Receive-job tests' {
127+
It 'Can Receive-Job with state change events' {
128+
$result = Start-Job -Name 'ReceiveWriteEventsJob' -ScriptBlock { 1 + 1 } | Receive-Job -Wait -WriteEvents
129+
$result.Count | Should Be 3
130+
$result[0] | Should Be 2
131+
$result[1].GetType().FullName | Should BeExactly 'System.Management.Automation.JobStateEventArgs'
29132
}
30-
finally {
31-
Remove-Job $nativeJob -Force -ErrorAction SilentlyContinue
133+
134+
It 'Can Receive-Job with job object and result' {
135+
$result = Start-Job -ScriptBlock { 1 + 1 } | Receive-Job -Wait -WriteJobInResults
136+
$result.Count | Should Be 2
137+
ValidateJobInfo -job $result[0] -command ' 1 + 1 ' -state 'Completed' -hasMoreData $false
138+
$result[1] | Should Be 2
139+
$result[0] | Remove-Job -Force -ErrorAction SilentlyContinue
140+
}
141+
142+
It 'Can Receive-Job and autoremove' {
143+
$result = Start-Job -Name 'ReceiveJobAutoRemove' -ScriptBlock { 1 + 1 } | Receive-Job -Wait -AutoRemoveJob
144+
$result | Should Be 2
145+
{ Get-Job -Name 'ReceiveJobAutoRemove' -ErrorAction Stop } | ShouldBeErrorId 'JobWithSpecifiedNameNotFound,Microsoft.PowerShell.Commands.GetJobCommand'
146+
}
147+
148+
It 'Can Receive-Job and keep results' {
149+
$job = Start-Job -ScriptBlock { 1 + 1 } | Wait-Job
150+
$result = Receive-Job -Keep -Job $job
151+
$result | Should Be 2
152+
$result2 = Receive-Job -Job $job
153+
$result2 | Should Be 2
154+
$result3 = Receive-Job -Job $job
155+
$result3 | Should BeNullOrEmpty
156+
$job | Remove-Job -Force -ErrorAction SilentlyContinue
157+
}
158+
159+
It 'Can Receive-Job with NoRecurse' {
160+
$job = Start-Job -ScriptBlock { 1 + 1 }
161+
$result = Receive-Job -Wait -NoRecurse -Job $job
162+
$result | Should BeNullOrEmpty
163+
$job | Remove-Job -Force -ErrorAction SilentlyContinue
164+
}
165+
166+
It 'Can Receive-Job using ComputerName' {
167+
$jobName = 'ReceiveUsingComputerName'
168+
$job = Start-Job -ScriptBlock { 1 + 1 } -Name $jobName | Wait-Job
169+
$result = Receive-Job -ComputerName localhost -Job $job
170+
$result | Should Be 2
171+
$job | Remove-Job -Force -ErrorAction SilentlyContinue
172+
}
173+
174+
It 'Can Receive-Job using Location' {
175+
$jobName = 'ReceiveUsingLocation'
176+
$job = Start-Job -ScriptBlock { 1 + 1 } -Name $jobName | Wait-Job
177+
$result = Receive-Job -Location localhost -Job $job
178+
$result | Should Be 2
179+
$job | Remove-Job -Force -ErrorAction SilentlyContinue
180+
}
181+
182+
It 'Can receive a job with -wait switch' {
183+
$job = Start-Job -ScriptBlock { 1 + 1 }
184+
$result = $job | Receive-Job -Wait
185+
ValidateJobInfo -job $job -state 'Completed' -hasMoreData $false -command ' 1 + 1 '
186+
$result | Should Be 2
32187
}
33188
}
34189

35-
AfterAll {
36-
Remove-Job $job -Force
190+
Context 'Get-Job tests' {
191+
BeforeAll {
192+
$getJobTestCases = @(
193+
@{ parameters = @{ Name = $startedJob.Name } ; property = 'Name'},
194+
@{ parameters = @{ Id = $startedJob.Id } ; property = 'Id'},
195+
@{ parameters = @{ InstanceId = $startedJob.InstanceId } ; property = 'InstanceId'},
196+
@{ parameters = @{ State = $startedJob.State } ; property = 'State'}
197+
)
198+
199+
$getJobSwitches = @(
200+
@{ parameters = @{ Before = $timeAfterStartedJob }; property = '-Before'},
201+
@{ parameters = @{ After = $timeBeforeStartedJob }; property = '-After'},
202+
@{ parameters = @{ HasMoreData = $true }; property = '-HasMoreData'}
203+
)
204+
205+
$getJobChildJobs = @(
206+
@{ parameters = @{ IncludeChildJob = $true }; property = '-IncludeChildJob'},
207+
@{ parameters = @{ ChildJobState = 'Completed' }; property = '-ChildJobState'}
208+
)
209+
}
210+
211+
AfterEach {
212+
Get-Job | Where-Object { $_.Id -ne $startedJob.Id } | Remove-Job -ErrorAction SilentlyContinue -Force
213+
}
214+
215+
It 'Can Get-Job with <property>' -TestCases $getJobTestCases {
216+
param($parameters)
217+
$job = Get-Job @parameters
218+
ValidateJobInfo -job $job -state 'Completed' -hasMoreData $true -command ' 1 + 1 '
219+
}
220+
221+
It 'Can Get-Job with <property>' -TestCases $getJobSwitches {
222+
param($parameters)
223+
$job = Get-Job @parameters
224+
ValidateJobInfo -job $job -state 'Completed' -hasMoreData $true -Name 'StartedJob'
225+
}
226+
227+
It 'Can Get-Job with <property>' -TestCases $getJobChildJobs {
228+
param($parameters)
229+
$jobs = Get-Job @parameters
230+
$jobs.Count | Should Be 2
231+
ValidateJobInfo -job $jobs[0] -state 'Completed' -hasMoreData $true -Name 'StartedJob'
232+
ValidateJobInfo -job $jobs[1] -state 'Completed' -hasMoreData $true
233+
}
234+
}
235+
236+
237+
Context 'Remove-Job tests' {
238+
# The test pattern used here is different from other tests since there is a scoping issue in Pester.
239+
# If BeforeEach is used then $removeJobTestCases does not bind when the It is called.
240+
# This implementation works around the problem by using a BeforeAll and creating a job inside the It.
241+
BeforeAll {
242+
$removeJobTestCases = @(
243+
@{ property = 'Name'}
244+
@{ property = 'Id'}
245+
@{ property = 'InstanceId'}
246+
@{ property = 'State'}
247+
)
248+
}
249+
250+
It 'Can Remove-Job with <property>' -TestCases $removeJobTestCases {
251+
param($property)
252+
$jobToRemove = Start-Job -ScriptBlock { 1 + 1 } -Name 'JobToRemove' | Wait-Job
253+
$splat = @{ $property = $jobToRemove.$property }
254+
Remove-Job @splat
255+
Get-Job $jobToRemove -ErrorAction SilentlyContinue | Should BeNullOrEmpty
256+
}
257+
}
258+
259+
Context 'Stop-Job tests' {
260+
# The test pattern used here is different from other tests since there is a scoping issue in Pester.
261+
# If BeforeEach is used then $stopJobTestCases does not bind when the It is called.
262+
# This implementation works around the problem by using a BeforeAll and creating a job inside the It.
263+
BeforeAll {
264+
$stopJobTestCases = @(
265+
@{ property = 'Name'}
266+
@{ property = 'Id'}
267+
@{ property = 'InstanceId'}
268+
@{ property = 'State'}
269+
)
270+
# '-Seconds 100' is chosen to be substantially large, so that the job is in running state when Stop-Job is called.
271+
$jobToStop = Start-Job -ScriptBlock { Start-Sleep -Seconds 100 } -Name 'JobToStop'
272+
}
273+
274+
It 'Can Stop-Job with <property>' -TestCases $stopJobTestCases {
275+
param($property)
276+
$splat = @{ $property = $jobToStop.$property }
277+
Stop-Job @splat
278+
ValidateJobInfo -job $jobToStop -state 'Stopped' -hasMoreData $false
279+
}
280+
281+
AfterAll {
282+
Remove-Job $jobToStop -Force -ErrorAction SilentlyContinue
283+
}
37284
}
38-
}
285+
}

0 commit comments

Comments
 (0)