@@ -175,14 +175,9 @@ async fn run_tests(run_opts: &RunOptions) -> anyhow::Result<ExecutionStats> {
175
175
176
176
let mut runners = Vec :: new ( ) ;
177
177
178
- // Create up to parallelism collections of PHD framework settings. For the
179
- // most part we can reuse the same settings for all test-running tasks -
180
- // state is not mutably shared. The important exception is port ranges for
181
- // servers PHD will run, where we want non-overlapping port ranges to ensure
182
- // that concurrent tests don't accidentally use a neighbor's servers.
183
- for i in 0 ..parallelism {
184
- let port_range = ( 9000 + PORT_RANGE_PER_RUNNER * i)
185
- ..( 9000 + PORT_RANGE_PER_RUNNER * ( i + 1 ) ) ;
178
+ if parallelism == 1 {
179
+ // If there's only one test runner, the provided config is by definition
180
+ // not going to have issues with parallelism. Consume it directly.
186
181
let ctx_params = FrameworkParameters {
187
182
propolis_server_path : run_opts. propolis_server_cmd . clone ( ) ,
188
183
crucible_downstairs : run_opts. crucible_downstairs ( ) ?,
@@ -195,7 +190,7 @@ async fn run_tests(run_opts: &RunOptions) -> anyhow::Result<ExecutionStats> {
195
190
default_guest_memory_mib : run_opts. default_guest_memory_mib ,
196
191
default_guest_os_artifact : run_opts. default_guest_artifact . clone ( ) ,
197
192
default_bootrom_artifact : run_opts. default_bootrom_artifact . clone ( ) ,
198
- port_range,
193
+ port_range : 9000 .. ( 9000 + PORT_RANGE_PER_RUNNER ) ,
199
194
max_buildomat_wait : Duration :: from_secs (
200
195
run_opts. max_buildomat_wait_secs ,
201
196
) ,
@@ -209,6 +204,71 @@ async fn run_tests(run_opts: &RunOptions) -> anyhow::Result<ExecutionStats> {
209
204
210
205
let fixtures = TestFixtures :: new ( ctx. clone ( ) ) . unwrap ( ) ;
211
206
runners. push ( ( ctx, fixtures) ) ;
207
+ } else {
208
+ // Create up to parallelism collections of PHD framework settings. Many
209
+ // settings can be reused directly, but some describe state the
210
+ // framework will mutate (causing ports to be allocated, fetching
211
+ // artifacts, etc). Take the provided config and make it safe for
212
+ // Frameworks to use independently.
213
+ //
214
+ // This implies downloading artifacts {parallelism} times, extracting
215
+ // artifacts redundantly for the different artifact directories, makes
216
+ // terrible use of the port range. It'd be much better to accept some
217
+ // owner of the shared state that each Framework can take as a
218
+ // parameter.
219
+
220
+ // We'll separate directories by which Framework they're for in some
221
+ // cases, below. Those uniquifying names will be padded to all be the
222
+ // length of the longest uniquifier to help make it kind of legible..
223
+ let pad_size = format ! ( "{}" , parallelism - 1 ) . len ( ) ;
224
+
225
+ for i in 0 ..parallelism {
226
+ let port_range = ( 9000 + PORT_RANGE_PER_RUNNER * i)
227
+ ..( 9000 + PORT_RANGE_PER_RUNNER * ( i + 1 ) ) ;
228
+ let mut unshared_tmp_dir = run_opts. tmp_directory . clone ( ) ;
229
+ unshared_tmp_dir. push ( format ! ( "runner-{:pad_size$}" , i) ) ;
230
+
231
+ let mut unshared_artifacts_dir =
232
+ run_opts. artifact_directory ( ) . clone ( ) ;
233
+ unshared_artifacts_dir. push ( format ! ( "runner-{:pad_size$}" , i) ) ;
234
+
235
+ // The runner directories may well not exist, we just invented them
236
+ // after all. Create them so phd-runner can use them. This is awful.
237
+ // Sorry.
238
+ let _ = std:: fs:: create_dir ( & unshared_tmp_dir) ;
239
+ let _ = std:: fs:: create_dir ( & unshared_artifacts_dir) ;
240
+
241
+ let ctx_params = FrameworkParameters {
242
+ propolis_server_path : run_opts. propolis_server_cmd . clone ( ) ,
243
+ crucible_downstairs : run_opts. crucible_downstairs ( ) ?,
244
+ base_propolis : run_opts. base_propolis ( ) ,
245
+ tmp_directory : unshared_tmp_dir,
246
+ artifact_directory : unshared_artifacts_dir,
247
+ artifact_toml : run_opts. artifact_toml_path . clone ( ) ,
248
+ server_log_mode : run_opts. server_logging_mode ,
249
+ default_guest_cpus : run_opts. default_guest_cpus ,
250
+ default_guest_memory_mib : run_opts. default_guest_memory_mib ,
251
+ default_guest_os_artifact : run_opts
252
+ . default_guest_artifact
253
+ . clone ( ) ,
254
+ default_bootrom_artifact : run_opts
255
+ . default_bootrom_artifact
256
+ . clone ( ) ,
257
+ port_range,
258
+ max_buildomat_wait : Duration :: from_secs (
259
+ run_opts. max_buildomat_wait_secs ,
260
+ ) ,
261
+ } ;
262
+
263
+ let ctx = Arc :: new (
264
+ Framework :: new ( ctx_params)
265
+ . await
266
+ . expect ( "should be able to set up a test context" ) ,
267
+ ) ;
268
+
269
+ let fixtures = TestFixtures :: new ( ctx. clone ( ) ) . unwrap ( ) ;
270
+ runners. push ( ( ctx, fixtures) ) ;
271
+ }
212
272
}
213
273
214
274
// Run the tests and print results.
0 commit comments