6
6
//! benchmarks themselves) should be done via the `#[test]` and
7
7
//! `#[bench]` attributes.
8
8
//!
9
- //! See the [Testing Chapter](../book/ch11-00-testing.html) of the book for more details.
9
+ //! See the [Testing Chapter](../book/ch11-00-testing.html) of the book for more
10
+ //! details.
10
11
11
12
// Currently, not much of this is meant for users. It is intended to
12
13
// support the simplest interface possible for representing and
@@ -76,6 +77,7 @@ mod types;
76
77
#[ cfg( test) ]
77
78
mod tests;
78
79
80
+ use core:: any:: Any ;
79
81
use event:: { CompletedTest , TestEvent } ;
80
82
use helpers:: concurrency:: get_concurrency;
81
83
use helpers:: exit_code:: get_exit_code;
@@ -175,17 +177,20 @@ fn make_owned_test(test: &&TestDescAndFn) -> TestDescAndFn {
175
177
}
176
178
}
177
179
178
- /// Invoked when unit tests terminate. Should panic if the unit
179
- /// Tests is considered a failure. By default, invokes `report()`
180
- /// and checks for a `0` result.
181
- pub fn assert_test_result < T : Termination > ( result : T ) {
180
+ /// Invoked when unit tests terminate. Returns `Result::Err` if the test is
181
+ /// considered a failure. By default, invokes `report() and checks for a `0 `
182
+ /// result.
183
+ pub fn assert_test_result < T : Termination > ( result : T ) -> Result < ( ) , String > {
182
184
let code = result. report ( ) . to_i32 ( ) ;
183
- assert_eq ! (
184
- code, 0 ,
185
- "the test returned a termination value with a non-zero status code ({}) \
186
- which indicates a failure",
187
- code
188
- ) ;
185
+ if code == 0 {
186
+ Ok ( ( ) )
187
+ } else {
188
+ Err ( format ! (
189
+ "the test returned a termination value with a non-zero status code \
190
+ ({}) which indicates a failure",
191
+ code
192
+ ) )
193
+ }
189
194
}
190
195
191
196
pub fn run_tests < F > (
@@ -478,7 +483,7 @@ pub fn run_test(
478
483
id : TestId ,
479
484
desc : TestDesc ,
480
485
monitor_ch : Sender < CompletedTest > ,
481
- testfn : Box < dyn FnOnce ( ) + Send > ,
486
+ testfn : Box < dyn FnOnce ( ) -> Result < ( ) , String > + Send > ,
482
487
opts : TestRunOpts ,
483
488
) -> Option < thread:: JoinHandle < ( ) > > {
484
489
let concurrency = opts. concurrency ;
@@ -567,19 +572,19 @@ pub fn run_test(
567
572
568
573
/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`.
569
574
#[ inline( never) ]
570
- fn __rust_begin_short_backtrace < F : FnOnce ( ) > ( f : F ) {
571
- f ( ) ;
575
+ fn __rust_begin_short_backtrace < T , F : FnOnce ( ) -> T > ( f : F ) -> T {
576
+ let result = f ( ) ;
572
577
573
578
// prevent this frame from being tail-call optimised away
574
- black_box ( ( ) ) ;
579
+ black_box ( result )
575
580
}
576
581
577
582
fn run_test_in_process (
578
583
id : TestId ,
579
584
desc : TestDesc ,
580
585
nocapture : bool ,
581
586
report_time : bool ,
582
- testfn : Box < dyn FnOnce ( ) + Send > ,
587
+ testfn : Box < dyn FnOnce ( ) -> Result < ( ) , String > + Send > ,
583
588
monitor_ch : Sender < CompletedTest > ,
584
589
time_opts : Option < time:: TestTimeOptions > ,
585
590
) {
@@ -591,7 +596,7 @@ fn run_test_in_process(
591
596
}
592
597
593
598
let start = report_time. then ( Instant :: now) ;
594
- let result = catch_unwind ( AssertUnwindSafe ( testfn) ) ;
599
+ let result = fold_err ( catch_unwind ( AssertUnwindSafe ( testfn) ) ) ;
595
600
let exec_time = start. map ( |start| {
596
601
let duration = start. elapsed ( ) ;
597
602
TestExecTime ( duration)
@@ -608,6 +613,19 @@ fn run_test_in_process(
608
613
monitor_ch. send ( message) . unwrap ( ) ;
609
614
}
610
615
616
+ fn fold_err < T , E > (
617
+ result : Result < Result < T , E > , Box < dyn Any + Send > > ,
618
+ ) -> Result < T , Box < dyn Any + Send > >
619
+ where
620
+ E : Send + ' static ,
621
+ {
622
+ match result {
623
+ Ok ( Err ( e) ) => Err ( Box :: new ( e) ) ,
624
+ Ok ( Ok ( v) ) => Ok ( v) ,
625
+ Err ( e) => Err ( e) ,
626
+ }
627
+ }
628
+
611
629
fn spawn_test_subprocess (
612
630
id : TestId ,
613
631
desc : TestDesc ,
@@ -663,7 +681,10 @@ fn spawn_test_subprocess(
663
681
monitor_ch. send ( message) . unwrap ( ) ;
664
682
}
665
683
666
- fn run_test_in_spawned_subprocess ( desc : TestDesc , testfn : Box < dyn FnOnce ( ) + Send > ) -> ! {
684
+ fn run_test_in_spawned_subprocess (
685
+ desc : TestDesc ,
686
+ testfn : Box < dyn FnOnce ( ) -> Result < ( ) , String > + Send > ,
687
+ ) -> ! {
667
688
let builtin_panic_hook = panic:: take_hook ( ) ;
668
689
let record_result = Arc :: new ( move |panic_info : Option < & ' _ PanicInfo < ' _ > > | {
669
690
let test_result = match panic_info {
@@ -689,7 +710,9 @@ fn run_test_in_spawned_subprocess(desc: TestDesc, testfn: Box<dyn FnOnce() + Sen
689
710
} ) ;
690
711
let record_result2 = record_result. clone ( ) ;
691
712
panic:: set_hook ( Box :: new ( move |info| record_result2 ( Some ( & info) ) ) ) ;
692
- testfn ( ) ;
713
+ if let Err ( message) = testfn ( ) {
714
+ panic ! ( "{}" , message) ;
715
+ }
693
716
record_result ( None ) ;
694
717
unreachable ! ( "panic=abort callback should have exited the process" )
695
718
}
0 commit comments