@@ -98,32 +98,43 @@ pub(crate) fn run_tests(config: &Config, tests: Vec<CollectedTest>) -> bool {
9898fn spawn_test_thread (
9999 id : TestId ,
100100 test : & CollectedTest ,
101- completion_tx : mpsc:: Sender < TestCompletion > ,
101+ completion_sender : mpsc:: Sender < TestCompletion > ,
102102) -> Option < thread:: JoinHandle < ( ) > > {
103103 if test. desc . ignore && !test. config . run_ignored {
104- completion_tx
104+ completion_sender
105105 . send ( TestCompletion { id, outcome : TestOutcome :: Ignored , stdout : None } )
106106 . unwrap ( ) ;
107107 return None ;
108108 }
109109
110- let runnable_test = RunnableTest :: new ( test) ;
111- let should_panic = test. desc . should_panic ;
112- let run_test = move || run_test_inner ( id, should_panic, runnable_test, completion_tx) ;
113-
110+ let args = TestThreadArgs {
111+ id,
112+ config : Arc :: clone ( & test. config ) ,
113+ testpaths : test. testpaths . clone ( ) ,
114+ revision : test. revision . clone ( ) ,
115+ should_fail : test. desc . should_fail ,
116+ completion_sender,
117+ } ;
114118 let thread_builder = thread:: Builder :: new ( ) . name ( test. desc . name . clone ( ) ) ;
115- let join_handle = thread_builder. spawn ( run_test ) . unwrap ( ) ;
119+ let join_handle = thread_builder. spawn ( move || test_thread_main ( args ) ) . unwrap ( ) ;
116120 Some ( join_handle)
117121}
118122
119- /// Runs a single test, within the dedicated thread spawned by the caller .
120- fn run_test_inner (
123+ /// All of the owned data needed by `test_thread_main` .
124+ struct TestThreadArgs {
121125 id : TestId ,
122- should_panic : ShouldPanic ,
123- runnable_test : RunnableTest ,
126+
127+ config : Arc < Config > ,
128+ testpaths : TestPaths ,
129+ revision : Option < String > ,
130+ should_fail : ShouldFail ,
131+
124132 completion_sender : mpsc:: Sender < TestCompletion > ,
125- ) {
126- let capture = CaptureKind :: for_config ( & runnable_test. config ) ;
133+ }
134+
135+ /// Runs a single test, within the dedicated thread spawned by the caller.
136+ fn test_thread_main ( args : TestThreadArgs ) {
137+ let capture = CaptureKind :: for_config ( & args. config ) ;
127138
128139 // Install a panic-capture buffer for use by the custom panic hook.
129140 if capture. should_set_panic_hook ( ) {
@@ -133,24 +144,42 @@ fn run_test_inner(
133144 let stdout = capture. stdout ( ) ;
134145 let stderr = capture. stderr ( ) ;
135146
136- let panic_payload = panic:: catch_unwind ( move || runnable_test. run ( stdout, stderr) ) . err ( ) ;
147+ // Run the test, catching any panics so that we can gracefully report
148+ // failure (or success).
149+ //
150+ // FIXME(Zalathar): Ideally we would report test failures with `Result`,
151+ // and use panics only for bugs within compiletest itself, but that would
152+ // require a major overhaul of error handling in the test runners.
153+ let panic_payload = panic:: catch_unwind ( || {
154+ __rust_begin_short_backtrace ( || {
155+ crate :: runtest:: run (
156+ & args. config ,
157+ stdout,
158+ stderr,
159+ & args. testpaths ,
160+ args. revision . as_deref ( ) ,
161+ ) ;
162+ } ) ;
163+ } )
164+ . err ( ) ;
137165
138166 if let Some ( panic_buf) = panic_hook:: take_capture_buf ( ) {
139167 let panic_buf = panic_buf. lock ( ) . unwrap_or_else ( |e| e. into_inner ( ) ) ;
140168 // Forward any captured panic message to (captured) stderr.
141169 write ! ( stderr, "{panic_buf}" ) ;
142170 }
143171
144- let outcome = match ( should_panic, panic_payload) {
145- ( ShouldPanic :: No , None ) | ( ShouldPanic :: Yes , Some ( _) ) => TestOutcome :: Succeeded ,
146- ( ShouldPanic :: No , Some ( _) ) => TestOutcome :: Failed { message : None } ,
147- ( ShouldPanic :: Yes , None ) => {
148- TestOutcome :: Failed { message : Some ( "test did not panic as expected" ) }
172+ // Interpret the presence/absence of a panic as test failure/success.
173+ let outcome = match ( args. should_fail , panic_payload) {
174+ ( ShouldFail :: No , None ) | ( ShouldFail :: Yes , Some ( _) ) => TestOutcome :: Succeeded ,
175+ ( ShouldFail :: No , Some ( _) ) => TestOutcome :: Failed { message : None } ,
176+ ( ShouldFail :: Yes , None ) => {
177+ TestOutcome :: Failed { message : Some ( "`//@ should-fail` test did not fail as expected" ) }
149178 }
150179 } ;
151180
152181 let stdout = capture. into_inner ( ) ;
153- completion_sender. send ( TestCompletion { id, outcome, stdout } ) . unwrap ( ) ;
182+ args . completion_sender . send ( TestCompletion { id : args . id , outcome, stdout } ) . unwrap ( ) ;
154183}
155184
156185enum CaptureKind {
@@ -207,33 +236,6 @@ impl CaptureKind {
207236#[ derive( Clone , Copy , Debug , PartialEq , Eq , Hash ) ]
208237struct TestId ( usize ) ;
209238
210- struct RunnableTest {
211- config : Arc < Config > ,
212- testpaths : TestPaths ,
213- revision : Option < String > ,
214- }
215-
216- impl RunnableTest {
217- fn new ( test : & CollectedTest ) -> Self {
218- let config = Arc :: clone ( & test. config ) ;
219- let testpaths = test. testpaths . clone ( ) ;
220- let revision = test. revision . clone ( ) ;
221- Self { config, testpaths, revision }
222- }
223-
224- fn run ( & self , stdout : & dyn ConsoleOut , stderr : & dyn ConsoleOut ) {
225- __rust_begin_short_backtrace ( || {
226- crate :: runtest:: run (
227- Arc :: clone ( & self . config ) ,
228- stdout,
229- stderr,
230- & self . testpaths ,
231- self . revision . as_deref ( ) ,
232- ) ;
233- } ) ;
234- }
235- }
236-
237239/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`.
238240#[ inline( never) ]
239241fn __rust_begin_short_backtrace < T , F : FnOnce ( ) -> T > ( f : F ) -> T {
@@ -336,7 +338,7 @@ pub(crate) struct CollectedTestDesc {
336338 pub ( crate ) filterable_path : Utf8PathBuf ,
337339 pub ( crate ) ignore : bool ,
338340 pub ( crate ) ignore_message : Option < Cow < ' static , str > > ,
339- pub ( crate ) should_panic : ShouldPanic ,
341+ pub ( crate ) should_fail : ShouldFail ,
340342}
341343
342344/// Whether console output should be colored or not.
@@ -348,9 +350,10 @@ pub enum ColorConfig {
348350 NeverColor ,
349351}
350352
351- /// Whether test is expected to panic or not.
353+ /// Tests with `//@ should-fail` are tests of compiletest itself, and should
354+ /// be reported as successful if and only if they would have _failed_.
352355#[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash ) ]
353- pub ( crate ) enum ShouldPanic {
356+ pub ( crate ) enum ShouldFail {
354357 No ,
355358 Yes ,
356359}
0 commit comments