@@ -39,6 +39,7 @@ impl DocTestRunner {
3939 doctest : & DocTestBuilder ,
4040 scraped_test : & ScrapedDocTest ,
4141 target_str : & str ,
42+ opts : & RustdocOptions ,
4243 ) {
4344 let ignore = match scraped_test. langstr . ignore {
4445 Ignore :: All => true ,
@@ -62,6 +63,7 @@ impl DocTestRunner {
6263 self . nb_tests,
6364 & mut self . output,
6465 & mut self . output_merged_tests,
66+ opts,
6567 ) ,
6668 ) ) ;
6769 self . supports_color &= doctest. supports_color ;
@@ -134,13 +136,41 @@ mod __doctest_mod {{
134136 }}
135137
136138 #[allow(unused)]
137- pub fn doctest_runner(bin: &std::path::Path, test_nb: usize) -> ExitCode {{
139+ pub fn doctest_runner(bin: &std::path::Path, test_nb: usize, should_panic: bool ) -> ExitCode {{
138140 let out = std::process::Command::new(bin)
139141 .env(self::RUN_OPTION, test_nb.to_string())
140142 .args(std::env::args().skip(1).collect::<Vec<_>>())
141143 .output()
142144 .expect(\" failed to run command\" );
143- if !out.status.success() {{
145+ if should_panic {{
146+ // FIXME: Make `test::get_result_from_exit_code` public and use this code instead of this.
147+ //
148+ // On Zircon (the Fuchsia kernel), an abort from userspace calls the
149+ // LLVM implementation of __builtin_trap(), e.g., ud2 on x86, which
150+ // raises a kernel exception. If a userspace process does not
151+ // otherwise arrange exception handling, the kernel kills the process
152+ // with this return code.
153+ #[cfg(target_os = \" fuchsia\" )]
154+ const ZX_TASK_RETCODE_EXCEPTION_KILL: i32 = -1028;
155+ // On Windows we use __fastfail to abort, which is documented to use this
156+ // exception code.
157+ #[cfg(windows)]
158+ const STATUS_FAIL_FAST_EXCEPTION: i32 = 0xC0000409u32 as i32;
159+ #[cfg(unix)]
160+ const SIGABRT: std::ffi::c_int = 6;
161+
162+ match out.status.code() {{
163+ Some(test::ERROR_EXIT_CODE) => ExitCode::SUCCESS,
164+ #[cfg(windows)]
165+ Some(STATUS_FAIL_FAST_EXCEPTION) => ExitCode::SUCCESS,
166+ #[cfg(unix)]
167+ None if out.status.signal() == Some(libc::SIGABRT) => ExitCode::SUCCESS,
168+ // Upon an abort, Fuchsia returns the status code ZX_TASK_RETCODE_EXCEPTION_KILL.
169+ #[cfg(target_os = \" fuchsia\" )]
170+ Some(ZX_TASK_RETCODE_EXCEPTION_KILL) => ExitCode::SUCCESS,
171+ _ => ExitCode::FAILURE,
172+ }}
173+ }} else if !out.status.success() {{
144174 if let Some(code) = out.status.code() {{
145175 eprintln!(\" Test executable failed (exit status: {{code}}).\" );
146176 }} else {{
@@ -223,6 +253,7 @@ fn generate_mergeable_doctest(
223253 id : usize ,
224254 output : & mut String ,
225255 output_merged_tests : & mut String ,
256+ opts : & RustdocOptions ,
226257) -> String {
227258 let test_id = format ! ( "__doctest_{id}" ) ;
228259
@@ -256,31 +287,33 @@ fn main() {returns_result} {{
256287 )
257288 . unwrap ( ) ;
258289 }
259- let not_running = ignore || scraped_test. langstr . no_run ;
290+ let should_panic = scraped_test. langstr . should_panic ;
291+ let not_running = ignore || scraped_test. no_run ( opts) ;
260292 writeln ! (
261293 output_merged_tests,
262294 "
263295mod {test_id} {{
264296pub const TEST: test::TestDescAndFn = test::TestDescAndFn::new_doctest(
265- {test_name:?}, {ignore}, {file:?}, {line}, {no_run}, {should_panic} ,
297+ {test_name:?}, {ignore} || ({should_panic} && crate::__doctest_mod::SHOULD_PANIC_DISABLED) , {file:?}, {line}, {no_run}, false ,
266298test::StaticTestFn(
267299 || {{{runner}}},
268300));
269301}}" ,
270302 test_name = scraped_test. name,
271303 file = scraped_test. path( ) ,
272304 line = scraped_test. line,
273- no_run = scraped_test. langstr. no_run,
274- should_panic = !scraped_test. langstr. no_run && scraped_test. langstr. should_panic,
305+ no_run = scraped_test. no_run( opts) ,
275306 // Setting `no_run` to `true` in `TestDesc` still makes the test run, so we simply
276307 // don't give it the function to run.
277308 runner = if not_running {
278309 "test::assert_test_result(Ok::<(), String>(()))" . to_string( )
279310 } else {
280311 format!(
281312 "
282- if let Some(bin_path) = crate::__doctest_mod::doctest_path() {{
283- test::assert_test_result(crate::__doctest_mod::doctest_runner(bin_path, {id}))
313+ if {should_panic} && crate::__doctest_mod::SHOULD_PANIC_DISABLED {{
314+ test::assert_test_result(Ok::<(), String>(()))
315+ }} else if let Some(bin_path) = crate::__doctest_mod::doctest_path() {{
316+ test::assert_test_result(crate::__doctest_mod::doctest_runner(bin_path, {id}, {should_panic}))
284317}} else {{
285318 test::assert_test_result(doctest_bundle::{test_id}::__main_fn())
286319}}
0 commit comments