25
25
#![ feature( nll) ]
26
26
#![ feature( available_concurrency) ]
27
27
#![ feature( internal_output_capture) ]
28
+ #![ feature( option_unwrap_none) ]
28
29
#![ feature( panic_unwind) ]
29
30
#![ feature( staged_api) ]
30
31
#![ feature( termination_trait_lib) ]
@@ -208,9 +209,15 @@ where
208
209
use std:: collections:: { self , HashMap } ;
209
210
use std:: hash:: BuildHasherDefault ;
210
211
use std:: sync:: mpsc:: RecvTimeoutError ;
212
+
213
+ struct RunningTest {
214
+ timeout : Instant ,
215
+ join_handle : Option < thread:: JoinHandle < ( ) > > ,
216
+ }
217
+
211
218
// Use a deterministic hasher
212
219
type TestMap =
213
- HashMap < TestDesc , Instant , BuildHasherDefault < collections:: hash_map:: DefaultHasher > > ;
220
+ HashMap < TestDesc , RunningTest , BuildHasherDefault < collections:: hash_map:: DefaultHasher > > ;
214
221
215
222
let tests_len = tests. len ( ) ;
216
223
@@ -260,7 +267,11 @@ where
260
267
let now = Instant :: now ( ) ;
261
268
let timed_out = running_tests
262
269
. iter ( )
263
- . filter_map ( |( desc, timeout) | if & now >= timeout { Some ( desc. clone ( ) ) } else { None } )
270
+ . filter_map (
271
+ |( desc, running_test) | {
272
+ if now >= running_test. timeout { Some ( desc. clone ( ) ) } else { None }
273
+ } ,
274
+ )
264
275
. collect ( ) ;
265
276
for test in & timed_out {
266
277
running_tests. remove ( test) ;
@@ -269,9 +280,9 @@ where
269
280
}
270
281
271
282
fn calc_timeout ( running_tests : & TestMap ) -> Option < Duration > {
272
- running_tests. values ( ) . min ( ) . map ( |next_timeout| {
283
+ running_tests. values ( ) . map ( |running_test| running_test . timeout ) . min ( ) . map ( |next_timeout| {
273
284
let now = Instant :: now ( ) ;
274
- if * next_timeout >= now { * next_timeout - now } else { Duration :: new ( 0 , 0 ) }
285
+ if next_timeout >= now { next_timeout - now } else { Duration :: new ( 0 , 0 ) }
275
286
} )
276
287
}
277
288
@@ -280,7 +291,8 @@ where
280
291
let test = remaining. pop ( ) . unwrap ( ) ;
281
292
let event = TestEvent :: TeWait ( test. desc . clone ( ) ) ;
282
293
notify_about_test_event ( event) ?;
283
- run_test ( opts, !opts. run_tests , test, run_strategy, tx. clone ( ) , Concurrent :: No ) ;
294
+ run_test ( opts, !opts. run_tests , test, run_strategy, tx. clone ( ) , Concurrent :: No )
295
+ . unwrap_none ( ) ;
284
296
let completed_test = rx. recv ( ) . unwrap ( ) ;
285
297
286
298
let event = TestEvent :: TeResult ( completed_test) ;
@@ -291,11 +303,19 @@ where
291
303
while pending < concurrency && !remaining. is_empty ( ) {
292
304
let test = remaining. pop ( ) . unwrap ( ) ;
293
305
let timeout = time:: get_default_test_timeout ( ) ;
294
- running_tests . insert ( test. desc . clone ( ) , timeout ) ;
306
+ let desc = test. desc . clone ( ) ;
295
307
296
308
let event = TestEvent :: TeWait ( test. desc . clone ( ) ) ;
297
309
notify_about_test_event ( event) ?; //here no pad
298
- run_test ( opts, !opts. run_tests , test, run_strategy, tx. clone ( ) , Concurrent :: Yes ) ;
310
+ let join_handle = run_test (
311
+ opts,
312
+ !opts. run_tests ,
313
+ test,
314
+ run_strategy,
315
+ tx. clone ( ) ,
316
+ Concurrent :: Yes ,
317
+ ) ;
318
+ running_tests. insert ( desc, RunningTest { timeout, join_handle } ) ;
299
319
pending += 1 ;
300
320
}
301
321
@@ -323,8 +343,16 @@ where
323
343
}
324
344
}
325
345
326
- let completed_test = res. unwrap ( ) ;
327
- running_tests. remove ( & completed_test. desc ) ;
346
+ let mut completed_test = res. unwrap ( ) ;
347
+ let running_test = running_tests. remove ( & completed_test. desc ) . unwrap ( ) ;
348
+ if let Some ( join_handle) = running_test. join_handle {
349
+ if let Err ( _) = join_handle. join ( ) {
350
+ if let TrOk = completed_test. result {
351
+ completed_test. result =
352
+ TrFailedMsg ( "panicked after reporting success" . to_string ( ) ) ;
353
+ }
354
+ }
355
+ }
328
356
329
357
let event = TestEvent :: TeResult ( completed_test) ;
330
358
notify_about_test_event ( event) ?;
@@ -415,7 +443,7 @@ pub fn run_test(
415
443
strategy : RunStrategy ,
416
444
monitor_ch : Sender < CompletedTest > ,
417
445
concurrency : Concurrent ,
418
- ) {
446
+ ) -> Option < thread :: JoinHandle < ( ) > > {
419
447
let TestDescAndFn { desc, testfn } = test;
420
448
421
449
// Emscripten can catch panics but other wasm targets cannot
@@ -426,7 +454,7 @@ pub fn run_test(
426
454
if force_ignore || desc. ignore || ignore_because_no_process_support {
427
455
let message = CompletedTest :: new ( desc, TrIgnored , None , Vec :: new ( ) ) ;
428
456
monitor_ch. send ( message) . unwrap ( ) ;
429
- return ;
457
+ return None ;
430
458
}
431
459
432
460
struct TestRunOpts {
@@ -441,7 +469,7 @@ pub fn run_test(
441
469
monitor_ch : Sender < CompletedTest > ,
442
470
testfn : Box < dyn FnOnce ( ) + Send > ,
443
471
opts : TestRunOpts ,
444
- ) {
472
+ ) -> Option < thread :: JoinHandle < ( ) > > {
445
473
let concurrency = opts. concurrency ;
446
474
let name = desc. name . clone ( ) ;
447
475
@@ -469,9 +497,10 @@ pub fn run_test(
469
497
let supports_threads = !cfg ! ( target_os = "emscripten" ) && !cfg ! ( target_arch = "wasm32" ) ;
470
498
if concurrency == Concurrent :: Yes && supports_threads {
471
499
let cfg = thread:: Builder :: new ( ) . name ( name. as_slice ( ) . to_owned ( ) ) ;
472
- cfg. spawn ( runtest) . unwrap ( ) ;
500
+ Some ( cfg. spawn ( runtest) . unwrap ( ) )
473
501
} else {
474
502
runtest ( ) ;
503
+ None
475
504
}
476
505
}
477
506
@@ -484,10 +513,12 @@ pub fn run_test(
484
513
crate :: bench:: benchmark ( desc, monitor_ch, opts. nocapture , |harness| {
485
514
bencher. run ( harness)
486
515
} ) ;
516
+ None
487
517
}
488
518
StaticBenchFn ( benchfn) => {
489
519
// Benchmarks aren't expected to panic, so we run them all in-process.
490
520
crate :: bench:: benchmark ( desc, monitor_ch, opts. nocapture , benchfn) ;
521
+ None
491
522
}
492
523
DynTestFn ( f) => {
493
524
match strategy {
@@ -499,7 +530,7 @@ pub fn run_test(
499
530
monitor_ch,
500
531
Box :: new ( move || __rust_begin_short_backtrace ( f) ) ,
501
532
test_run_opts,
502
- ) ;
533
+ )
503
534
}
504
535
StaticTestFn ( f) => run_test_inner (
505
536
desc,
0 commit comments