Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit b7079c5

Browse files
Prevent merged doctests to break stdin if the generated file is too big
1 parent 23badff commit b7079c5

File tree

2 files changed

+50
-17
lines changed

2 files changed

+50
-17
lines changed

src/librustdoc/doctest.rs

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ pub(crate) fn run_tests(
289289
for (doctest, scraped_test) in &doctests {
290290
tests_runner.add_test(doctest, scraped_test, &target_str);
291291
}
292-
if let Ok(success) = tests_runner.run_tests(
292+
if let Ok(success) = tests_runner.run_merged_tests(
293293
rustdoc_test_options,
294294
edition,
295295
&opts,
@@ -454,6 +454,7 @@ fn run_test(
454454
doctest: RunnableDoctest,
455455
rustdoc_options: &RustdocOptions,
456456
supports_color: bool,
457+
is_multiple_tests: bool,
457458
report_unused_externs: impl Fn(UnusedExterns),
458459
) -> Result<(), TestFailure> {
459460
let langstr = &doctest.langstr;
@@ -474,11 +475,14 @@ fn run_test(
474475
}
475476

476477
compiler.arg("--edition").arg(&doctest.edition.to_string());
477-
compiler.env("UNSTABLE_RUSTDOC_TEST_PATH", &doctest.test_opts.path);
478-
compiler.env(
479-
"UNSTABLE_RUSTDOC_TEST_LINE",
480-
format!("{}", doctest.line as isize - doctest.full_test_line_offset as isize),
481-
);
478+
if !is_multiple_tests {
479+
// Setting these environment variables is unneeded if this is a merged doctest.
480+
compiler.env("UNSTABLE_RUSTDOC_TEST_PATH", &doctest.test_opts.path);
481+
compiler.env(
482+
"UNSTABLE_RUSTDOC_TEST_LINE",
483+
format!("{}", doctest.line as isize - doctest.full_test_line_offset as isize),
484+
);
485+
}
482486
compiler.arg("-o").arg(&output_file);
483487
if langstr.test_harness {
484488
compiler.arg("--test");
@@ -521,18 +525,37 @@ fn run_test(
521525
}
522526
}
523527

524-
compiler.arg("-");
525-
compiler.stdin(Stdio::piped());
526-
compiler.stderr(Stdio::piped());
528+
// If this is a merged doctest, we need to write it into a file instead of using stdin
529+
// because if the size of the merged doctests is too big, it'll simply break stdin.
530+
if is_multiple_tests {
531+
// It makes the compilation failure much faster if it is for a combined doctest.
532+
compiler.arg("--error-format=short");
533+
let input_file =
534+
doctest.test_opts.outdir.path().join(&format!("doctest_{}.rs", doctest.edition));
535+
if std::fs::write(&input_file, &doctest.full_test_code).is_err() {
536+
// If we cannot write this file for any reason, we leave. All combined tests will be
537+
// tested as standalone tests.
538+
return Err(TestFailure::CompileError);
539+
}
540+
compiler.arg(input_file);
541+
compiler.stderr(Stdio::null());
542+
} else {
543+
compiler.arg("-");
544+
compiler.stdin(Stdio::piped());
545+
compiler.stderr(Stdio::piped());
546+
}
527547

528548
debug!("compiler invocation for doctest: {compiler:?}");
529549

530550
let mut child = compiler.spawn().expect("Failed to spawn rustc process");
531-
{
551+
let output = if is_multiple_tests {
552+
let status = child.wait().expect("Failed to wait");
553+
process::Output { status, stdout: Vec::new(), stderr: Vec::new() }
554+
} else {
532555
let stdin = child.stdin.as_mut().expect("Failed to open stdin");
533556
stdin.write_all(doctest.full_test_code.as_bytes()).expect("could write out test sources");
534-
}
535-
let output = child.wait_with_output().expect("Failed to read stdout");
557+
child.wait_with_output().expect("Failed to read stdout")
558+
};
536559

537560
struct Bomb<'a>(&'a str);
538561
impl Drop for Bomb<'_> {
@@ -885,8 +908,13 @@ fn doctest_run_fn(
885908
edition: scraped_test.edition(&rustdoc_options),
886909
no_run: scraped_test.no_run(&rustdoc_options),
887910
};
888-
let res =
889-
run_test(runnable_test, &rustdoc_options, doctest.supports_color, report_unused_externs);
911+
let res = run_test(
912+
runnable_test,
913+
&rustdoc_options,
914+
doctest.supports_color,
915+
false,
916+
report_unused_externs,
917+
);
890918

891919
if let Err(err) = res {
892920
match err {

src/librustdoc/doctest/runner.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ impl DocTestRunner {
6262
self.nb_tests += 1;
6363
}
6464

65-
pub(crate) fn run_tests(
65+
pub(crate) fn run_merged_tests(
6666
&mut self,
6767
test_options: IndividualTestOptions,
6868
edition: Edition,
@@ -123,8 +123,13 @@ test::test_main(&[{test_args}], vec![{ids}], None);
123123
edition,
124124
no_run: false,
125125
};
126-
let ret =
127-
run_test(runnable_test, rustdoc_options, self.supports_color, |_: UnusedExterns| {});
126+
let ret = run_test(
127+
runnable_test,
128+
rustdoc_options,
129+
self.supports_color,
130+
true,
131+
|_: UnusedExterns| {},
132+
);
128133
if let Err(TestFailure::CompileError) = ret { Err(()) } else { Ok(ret.is_ok()) }
129134
}
130135
}

0 commit comments

Comments
 (0)