Use environment variables instead of command line arguments for merged doctests

This commit is contained in:
Guillaume Gomez 2024-10-01 16:23:04 +02:00
parent 612796c420
commit e904761231
2 changed files with 17 additions and 28 deletions

View File

@ -644,8 +644,7 @@ fn run_test(
} else {
cmd = Command::new(&output_file);
if doctest.is_multiple_tests {
cmd.arg("*doctest-bin-path");
cmd.arg(&output_file);
cmd.env("RUSTDOC_DOCTEST_BIN_PATH", &output_file);
}
}
if let Some(run_directory) = &rustdoc_options.test_run_directory {

View File

@ -112,8 +112,7 @@ mod __doctest_mod {{
use std::path::PathBuf;
pub static BINARY_PATH: OnceLock<PathBuf> = OnceLock::new();
pub const RUN_OPTION: &str = \"*doctest-inner-test\";
pub const BIN_OPTION: &str = \"*doctest-bin-path\";
pub const RUN_OPTION: &str = \"RUSTDOC_DOCTEST_RUN_NB_TEST\";
#[allow(unused)]
pub fn doctest_path() -> Option<&'static PathBuf> {{
@ -123,8 +122,8 @@ mod __doctest_mod {{
#[allow(unused)]
pub fn doctest_runner(bin: &std::path::Path, test_nb: usize) -> Result<(), String> {{
let out = std::process::Command::new(bin)
.arg(self::RUN_OPTION)
.arg(test_nb.to_string())
.env(self::RUN_OPTION, test_nb.to_string())
.args(std::env::args().skip(1).collect::<Vec<_>>())
.output()
.expect(\"failed to run command\");
if !out.status.success() {{
@ -138,36 +137,27 @@ mod __doctest_mod {{
#[rustc_main]
fn main() -> std::process::ExitCode {{
const TESTS: [test::TestDescAndFn; {nb_tests}] = [{ids}];
let bin_marker = std::ffi::OsStr::new(__doctest_mod::BIN_OPTION);
let test_marker = std::ffi::OsStr::new(__doctest_mod::RUN_OPTION);
let test_args = &[{test_args}];
const ENV_BIN: &'static str = \"RUSTDOC_DOCTEST_BIN_PATH\";
let mut args = std::env::args_os().skip(1);
while let Some(arg) = args.next() {{
if arg == bin_marker {{
let Some(binary) = args.next() else {{
panic!(\"missing argument after `{{}}`\", __doctest_mod::BIN_OPTION);
}};
if crate::__doctest_mod::BINARY_PATH.set(binary.into()).is_err() {{
panic!(\"`{{}}` option was used more than once\", bin_marker.to_string_lossy());
}}
return std::process::Termination::report(test::test_main(test_args, Vec::from(TESTS), None));
}} else if arg == test_marker {{
let Some(nb_test) = args.next() else {{
panic!(\"missing argument after `{{}}`\", __doctest_mod::RUN_OPTION);
}};
if let Some(nb_test) = nb_test.to_str().and_then(|nb| nb.parse::<usize>().ok()) {{
if let Some(test) = TESTS.get(nb_test) {{
if let test::StaticTestFn(f) = test.testfn {{
return std::process::Termination::report(f());
}}
if let Ok(binary) = std::env::var(ENV_BIN) {{
let _ = crate::__doctest_mod::BINARY_PATH.set(binary.into());
unsafe {{ std::env::remove_var(ENV_BIN); }}
return std::process::Termination::report(test::test_main(test_args, Vec::from(TESTS), None));
}} else if let Ok(nb_test) = std::env::var(__doctest_mod::RUN_OPTION) {{
if let Ok(nb_test) = nb_test.parse::<usize>() {{
if let Some(test) = TESTS.get(nb_test) {{
if let test::StaticTestFn(f) = test.testfn {{
return std::process::Termination::report(f());
}}
}}
panic!(\"Unexpected value after `{{}}`\", __doctest_mod::RUN_OPTION);
}}
panic!(\"Unexpected value for `{{}}`\", __doctest_mod::RUN_OPTION);
}}
eprintln!(\"WARNING: No argument provided so doctests will be run in the same process\");
eprintln!(\"WARNING: No rustdoc doctest environment variable provided so doctests will be run in \
the same process\");
std::process::Termination::report(test::test_main(test_args, Vec::from(TESTS), None))
}}",
nb_tests = self.nb_tests,