@@ -92,6 +92,7 @@ use time::TestExecTime;
92
92
const ERROR_EXIT_CODE : i32 = 101 ;
93
93
94
94
const SECONDARY_TEST_INVOKER_VAR : & str = "__RUST_TEST_INVOKE" ;
95
+ const SECONDARY_TEST_BENCH_BENCHMARKS_VAR : & str = "__RUST_TEST_BENCH_BENCHMARKS" ;
95
96
96
97
// The default console test runner. It accepts the command line
97
98
// arguments and a vector of test_descs.
@@ -171,18 +172,32 @@ pub fn test_main_static_abort(tests: &[&TestDescAndFn]) {
171
172
// will then exit the process.
172
173
if let Ok ( name) = env:: var ( SECONDARY_TEST_INVOKER_VAR ) {
173
174
env:: remove_var ( SECONDARY_TEST_INVOKER_VAR ) ;
175
+
176
+ // Convert benchmarks to tests if we're not benchmarking.
177
+ let mut tests = tests. iter ( ) . map ( make_owned_test) . collect :: < Vec < _ > > ( ) ;
178
+ if env:: var ( SECONDARY_TEST_BENCH_BENCHMARKS_VAR ) . is_ok ( ) {
179
+ env:: remove_var ( SECONDARY_TEST_BENCH_BENCHMARKS_VAR ) ;
180
+ } else {
181
+ tests = convert_benchmarks_to_tests ( tests) ;
182
+ } ;
183
+
174
184
let test = tests
175
- . iter ( )
185
+ . into_iter ( )
176
186
. filter ( |test| test. desc . name . as_slice ( ) == name)
177
- . map ( make_owned_test)
178
187
. next ( )
179
188
. unwrap_or_else ( || panic ! ( "couldn't find a test with the provided name '{name}'" ) ) ;
180
189
let TestDescAndFn { desc, testfn } = test;
181
- let testfn = match testfn {
182
- StaticTestFn ( f) => f,
183
- _ => panic ! ( "only static tests are supported" ) ,
184
- } ;
185
- run_test_in_spawned_subprocess ( desc, Box :: new ( testfn) ) ;
190
+ match testfn. into_runnable ( ) {
191
+ Runnable :: Test ( runnable_test) => {
192
+ if runnable_test. is_dynamic ( ) {
193
+ panic ! ( "only static tests are supported" ) ;
194
+ }
195
+ run_test_in_spawned_subprocess ( desc, runnable_test) ;
196
+ }
197
+ Runnable :: Bench ( _) => {
198
+ panic ! ( "benchmarks should not be executed into child processes" )
199
+ }
200
+ }
186
201
}
187
202
188
203
let args = env:: args ( ) . collect :: < Vec < _ > > ( ) ;
@@ -234,16 +249,6 @@ impl FilteredTests {
234
249
self . tests . push ( ( TestId ( self . next_id ) , test) ) ;
235
250
self . next_id += 1 ;
236
251
}
237
- fn add_bench_as_test (
238
- & mut self ,
239
- desc : TestDesc ,
240
- benchfn : impl Fn ( & mut Bencher ) -> Result < ( ) , String > + Send + ' static ,
241
- ) {
242
- let testfn = DynTestFn ( Box :: new ( move || {
243
- bench:: run_once ( |b| __rust_begin_short_backtrace ( || benchfn ( b) ) )
244
- } ) ) ;
245
- self . add_test ( desc, testfn) ;
246
- }
247
252
fn total_len ( & self ) -> usize {
248
253
self . tests . len ( ) + self . benches . len ( )
249
254
}
@@ -301,14 +306,14 @@ where
301
306
if opts. bench_benchmarks {
302
307
filtered. add_bench ( desc, DynBenchFn ( benchfn) ) ;
303
308
} else {
304
- filtered. add_bench_as_test ( desc, benchfn) ;
309
+ filtered. add_test ( desc, DynBenchAsTestFn ( benchfn) ) ;
305
310
}
306
311
}
307
312
StaticBenchFn ( benchfn) => {
308
313
if opts. bench_benchmarks {
309
314
filtered. add_bench ( desc, StaticBenchFn ( benchfn) ) ;
310
315
} else {
311
- filtered. add_bench_as_test ( desc, benchfn) ;
316
+ filtered. add_test ( desc, StaticBenchAsTestFn ( benchfn) ) ;
312
317
}
313
318
}
314
319
testfn => {
@@ -519,12 +524,8 @@ pub fn convert_benchmarks_to_tests(tests: Vec<TestDescAndFn>) -> Vec<TestDescAnd
519
524
. into_iter ( )
520
525
. map ( |x| {
521
526
let testfn = match x. testfn {
522
- DynBenchFn ( benchfn) => DynTestFn ( Box :: new ( move || {
523
- bench:: run_once ( |b| __rust_begin_short_backtrace ( || benchfn ( b) ) )
524
- } ) ) ,
525
- StaticBenchFn ( benchfn) => DynTestFn ( Box :: new ( move || {
526
- bench:: run_once ( |b| __rust_begin_short_backtrace ( || benchfn ( b) ) )
527
- } ) ) ,
527
+ DynBenchFn ( benchfn) => DynBenchAsTestFn ( benchfn) ,
528
+ StaticBenchFn ( benchfn) => StaticBenchAsTestFn ( benchfn) ,
528
529
f => f,
529
530
} ;
530
531
TestDescAndFn { desc : x. desc , testfn }
@@ -553,99 +554,69 @@ pub fn run_test(
553
554
return None ;
554
555
}
555
556
556
- struct TestRunOpts {
557
- pub strategy : RunStrategy ,
558
- pub nocapture : bool ,
559
- pub time : Option < time:: TestTimeOptions > ,
560
- }
557
+ match testfn. into_runnable ( ) {
558
+ Runnable :: Test ( runnable_test) => {
559
+ if runnable_test. is_dynamic ( ) {
560
+ match strategy {
561
+ RunStrategy :: InProcess => ( ) ,
562
+ _ => panic ! ( "Cannot run dynamic test fn out-of-process" ) ,
563
+ } ;
564
+ }
561
565
562
- fn run_test_inner (
563
- id : TestId ,
564
- desc : TestDesc ,
565
- monitor_ch : Sender < CompletedTest > ,
566
- testfn : Box < dyn FnOnce ( ) -> Result < ( ) , String > + Send > ,
567
- opts : TestRunOpts ,
568
- ) -> Option < thread:: JoinHandle < ( ) > > {
569
- let name = desc. name . clone ( ) ;
570
-
571
- let runtest = move || match opts. strategy {
572
- RunStrategy :: InProcess => run_test_in_process (
573
- id,
574
- desc,
575
- opts. nocapture ,
576
- opts. time . is_some ( ) ,
577
- testfn,
578
- monitor_ch,
579
- opts. time ,
580
- ) ,
581
- RunStrategy :: SpawnPrimary => spawn_test_subprocess (
582
- id,
583
- desc,
584
- opts. nocapture ,
585
- opts. time . is_some ( ) ,
586
- monitor_ch,
587
- opts. time ,
588
- ) ,
589
- } ;
566
+ let name = desc. name . clone ( ) ;
567
+ let nocapture = opts. nocapture ;
568
+ let time_options = opts. time_options ;
569
+ let bench_benchmarks = opts. bench_benchmarks ;
570
+
571
+ let runtest = move || match strategy {
572
+ RunStrategy :: InProcess => run_test_in_process (
573
+ id,
574
+ desc,
575
+ nocapture,
576
+ time_options. is_some ( ) ,
577
+ runnable_test,
578
+ monitor_ch,
579
+ time_options,
580
+ ) ,
581
+ RunStrategy :: SpawnPrimary => spawn_test_subprocess (
582
+ id,
583
+ desc,
584
+ nocapture,
585
+ time_options. is_some ( ) ,
586
+ monitor_ch,
587
+ time_options,
588
+ bench_benchmarks,
589
+ ) ,
590
+ } ;
590
591
591
- // If the platform is single-threaded we're just going to run
592
- // the test synchronously, regardless of the concurrency
593
- // level.
594
- let supports_threads = !cfg ! ( target_os = "emscripten" ) && !cfg ! ( target_family = "wasm" ) ;
595
- if supports_threads {
596
- let cfg = thread:: Builder :: new ( ) . name ( name. as_slice ( ) . to_owned ( ) ) ;
597
- let mut runtest = Arc :: new ( Mutex :: new ( Some ( runtest) ) ) ;
598
- let runtest2 = runtest. clone ( ) ;
599
- match cfg. spawn ( move || runtest2. lock ( ) . unwrap ( ) . take ( ) . unwrap ( ) ( ) ) {
600
- Ok ( handle) => Some ( handle) ,
601
- Err ( e) if e. kind ( ) == io:: ErrorKind :: WouldBlock => {
602
- // `ErrorKind::WouldBlock` means hitting the thread limit on some
603
- // platforms, so run the test synchronously here instead.
604
- Arc :: get_mut ( & mut runtest) . unwrap ( ) . get_mut ( ) . unwrap ( ) . take ( ) . unwrap ( ) ( ) ;
605
- None
592
+ // If the platform is single-threaded we're just going to run
593
+ // the test synchronously, regardless of the concurrency
594
+ // level.
595
+ let supports_threads = !cfg ! ( target_os = "emscripten" ) && !cfg ! ( target_family = "wasm" ) ;
596
+ if supports_threads {
597
+ let cfg = thread:: Builder :: new ( ) . name ( name. as_slice ( ) . to_owned ( ) ) ;
598
+ let mut runtest = Arc :: new ( Mutex :: new ( Some ( runtest) ) ) ;
599
+ let runtest2 = runtest. clone ( ) ;
600
+ match cfg. spawn ( move || runtest2. lock ( ) . unwrap ( ) . take ( ) . unwrap ( ) ( ) ) {
601
+ Ok ( handle) => Some ( handle) ,
602
+ Err ( e) if e. kind ( ) == io:: ErrorKind :: WouldBlock => {
603
+ // `ErrorKind::WouldBlock` means hitting the thread limit on some
604
+ // platforms, so run the test synchronously here instead.
605
+ Arc :: get_mut ( & mut runtest) . unwrap ( ) . get_mut ( ) . unwrap ( ) . take ( ) . unwrap ( ) ( ) ;
606
+ None
607
+ }
608
+ Err ( e) => panic ! ( "failed to spawn thread to run test: {e}" ) ,
606
609
}
607
- Err ( e) => panic ! ( "failed to spawn thread to run test: {e}" ) ,
610
+ } else {
611
+ runtest ( ) ;
612
+ None
608
613
}
609
- } else {
610
- runtest ( ) ;
611
- None
612
614
}
613
- }
614
-
615
- let test_run_opts =
616
- TestRunOpts { strategy, nocapture : opts. nocapture , time : opts. time_options } ;
617
-
618
- match testfn {
619
- DynBenchFn ( benchfn) => {
615
+ Runnable :: Bench ( runnable_bench) => {
620
616
// Benchmarks aren't expected to panic, so we run them all in-process.
621
- crate :: bench :: benchmark ( id, desc, monitor_ch, opts. nocapture , benchfn ) ;
617
+ runnable_bench . run ( id, & desc, & monitor_ch, opts. nocapture ) ;
622
618
None
623
619
}
624
- StaticBenchFn ( benchfn) => {
625
- // Benchmarks aren't expected to panic, so we run them all in-process.
626
- crate :: bench:: benchmark ( id, desc, monitor_ch, opts. nocapture , benchfn) ;
627
- None
628
- }
629
- DynTestFn ( f) => {
630
- match strategy {
631
- RunStrategy :: InProcess => ( ) ,
632
- _ => panic ! ( "Cannot run dynamic test fn out-of-process" ) ,
633
- } ;
634
- run_test_inner (
635
- id,
636
- desc,
637
- monitor_ch,
638
- Box :: new ( move || __rust_begin_short_backtrace ( f) ) ,
639
- test_run_opts,
640
- )
641
- }
642
- StaticTestFn ( f) => run_test_inner (
643
- id,
644
- desc,
645
- monitor_ch,
646
- Box :: new ( move || __rust_begin_short_backtrace ( f) ) ,
647
- test_run_opts,
648
- ) ,
649
620
}
650
621
}
651
622
@@ -663,7 +634,7 @@ fn run_test_in_process(
663
634
desc : TestDesc ,
664
635
nocapture : bool ,
665
636
report_time : bool ,
666
- testfn : Box < dyn FnOnce ( ) -> Result < ( ) , String > + Send > ,
637
+ runnable_test : RunnableTest ,
667
638
monitor_ch : Sender < CompletedTest > ,
668
639
time_opts : Option < time:: TestTimeOptions > ,
669
640
) {
@@ -675,7 +646,7 @@ fn run_test_in_process(
675
646
}
676
647
677
648
let start = report_time. then ( Instant :: now) ;
678
- let result = fold_err ( catch_unwind ( AssertUnwindSafe ( testfn ) ) ) ;
649
+ let result = fold_err ( catch_unwind ( AssertUnwindSafe ( || runnable_test . run ( ) ) ) ) ;
679
650
let exec_time = start. map ( |start| {
680
651
let duration = start. elapsed ( ) ;
681
652
TestExecTime ( duration)
@@ -712,13 +683,17 @@ fn spawn_test_subprocess(
712
683
report_time : bool ,
713
684
monitor_ch : Sender < CompletedTest > ,
714
685
time_opts : Option < time:: TestTimeOptions > ,
686
+ bench_benchmarks : bool ,
715
687
) {
716
688
let ( result, test_output, exec_time) = ( || {
717
689
let args = env:: args ( ) . collect :: < Vec < _ > > ( ) ;
718
690
let current_exe = & args[ 0 ] ;
719
691
720
692
let mut command = Command :: new ( current_exe) ;
721
693
command. env ( SECONDARY_TEST_INVOKER_VAR , desc. name . as_slice ( ) ) ;
694
+ if bench_benchmarks {
695
+ command. env ( SECONDARY_TEST_BENCH_BENCHMARKS_VAR , "1" ) ;
696
+ }
722
697
if nocapture {
723
698
command. stdout ( process:: Stdio :: inherit ( ) ) ;
724
699
command. stderr ( process:: Stdio :: inherit ( ) ) ;
@@ -760,10 +735,7 @@ fn spawn_test_subprocess(
760
735
monitor_ch. send ( message) . unwrap ( ) ;
761
736
}
762
737
763
- fn run_test_in_spawned_subprocess (
764
- desc : TestDesc ,
765
- testfn : Box < dyn FnOnce ( ) -> Result < ( ) , String > + Send > ,
766
- ) -> ! {
738
+ fn run_test_in_spawned_subprocess ( desc : TestDesc , runnable_test : RunnableTest ) -> ! {
767
739
let builtin_panic_hook = panic:: take_hook ( ) ;
768
740
let record_result = Arc :: new ( move |panic_info : Option < & ' _ PanicInfo < ' _ > > | {
769
741
let test_result = match panic_info {
@@ -789,7 +761,7 @@ fn run_test_in_spawned_subprocess(
789
761
} ) ;
790
762
let record_result2 = record_result. clone ( ) ;
791
763
panic:: set_hook ( Box :: new ( move |info| record_result2 ( Some ( info) ) ) ) ;
792
- if let Err ( message) = testfn ( ) {
764
+ if let Err ( message) = runnable_test . run ( ) {
793
765
panic ! ( "{}" , message) ;
794
766
}
795
767
record_result ( None ) ;
0 commit comments