Skip to content

Commit b3261d5

Browse files
Improve handling of --persist-doctests with combined doctests and update associated test to check both combined and non-combined doctests
1 parent 76c9ae6 commit b3261d5

File tree

3 files changed

+49
-15
lines changed

3 files changed

+49
-15
lines changed

Diff for: src/librustdoc/doctest.rs

+37-11
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ enum TestFailure {
318318
UnexpectedRunPass,
319319
}
320320

321+
#[derive(Debug)]
321322
enum DirState {
322323
Temp(tempfile::TempDir),
323324
Perm(PathBuf),
@@ -372,21 +373,41 @@ pub(crate) struct DocTestInfo {
372373
path: PathBuf,
373374
}
374375

376+
fn build_test_dir(outdir: &Arc<DirState>, is_multiple_tests: bool) -> PathBuf {
377+
// Make sure we emit well-formed executable names for our target.
378+
let is_perm_dir = matches!(**outdir, DirState::Perm(..));
379+
let out_dir = outdir.path();
380+
let out_dir = if is_multiple_tests && is_perm_dir {
381+
// If this a "multiple tests" case and we generate it into a non temporary directory, we
382+
// want to put it into the parent instead.
383+
out_dir.parent().unwrap_or(out_dir)
384+
} else {
385+
out_dir
386+
};
387+
if is_perm_dir && let Err(err) = std::fs::create_dir_all(&out_dir) {
388+
eprintln!("Couldn't create directory for doctest executables: {err}");
389+
panic::resume_unwind(Box::new(()));
390+
}
391+
out_dir.into()
392+
}
393+
375394
fn run_test(
376395
test: String,
377396
supports_color: bool,
378397
test_info: Option<DocTestInfo>,
379398
rustdoc_options: Arc<IndividualTestOptions>,
380399
is_multiple_tests: bool,
381-
outdir: Arc<DirState>,
382400
mut lang_string: LangString,
383401
edition: Edition,
384402
report_unused_externs: impl Fn(UnusedExterns),
385403
no_run: bool,
404+
// Used to prevent overwriting a binary in case `--persist-doctests` is used.
405+
binary_extra: Option<&str>,
406+
out_dir: PathBuf,
386407
) -> Result<(), TestFailure> {
387-
// Make sure we emit well-formed executable names for our target.
388-
let rust_out = add_exe_suffix("rust_out".to_owned(), &rustdoc_options.target);
389-
let output_file = outdir.path().join(rust_out);
408+
let rust_out =
409+
add_exe_suffix(format!("rust_out{}", binary_extra.unwrap_or("")), &rustdoc_options.target);
410+
let output_file = out_dir.join(rust_out);
390411

391412
let rustc_binary = rustdoc_options
392413
.test_builder
@@ -722,6 +743,7 @@ impl DocTest {
722743
let Self {
723744
supports_color, rustdoc_test_options, lang_string, outdir, path, no_run, ..
724745
} = self;
746+
let out_dir = build_test_dir(&outdir, false);
725747
TestDescAndFn {
726748
desc: test::TestDesc {
727749
name: test::DynTestName(std::mem::replace(&mut self.name, String::new())),
@@ -748,12 +770,18 @@ impl DocTest {
748770
Some(DocTestInfo { line_offset, line: self.line, path }),
749771
rustdoc_test_options,
750772
false,
751-
outdir,
752773
lang_string,
753774
edition,
754775
report_unused_externs,
755776
no_run,
777+
None,
778+
out_dir,
756779
);
780+
// We need to move `outdir` into the closure to ensure the `TempDir` struct won't
781+
// be dropped before all tests have been run.
782+
//
783+
// The call to `drop` is only to make use of `outdir`.
784+
drop(outdir);
757785

758786
if let Err(err) = res {
759787
match err {
@@ -897,11 +925,6 @@ pub(crate) fn make_test(
897925
let mut path = path.clone();
898926
path.push(&test_id);
899927

900-
if let Err(err) = std::fs::create_dir_all(&path) {
901-
eprintln!("Couldn't create directory for doctest executables: {err}");
902-
panic::resume_unwind(Box::new(()));
903-
}
904-
905928
DirState::Perm(path)
906929
} else {
907930
DirState::Temp(get_doctest_dir().expect("rustdoc needs a tempdir"))
@@ -1379,17 +1402,20 @@ test::test_main(&[{test_args}], vec![{ids}], None);
13791402
ids = self.ids,
13801403
)
13811404
.expect("failed to generate test code");
1405+
let out_dir = build_test_dir(self.outdir, true);
13821406
let ret = run_test(
13831407
code,
13841408
self.supports_color,
13851409
None,
13861410
Arc::clone(self.rustdoc_test_options),
13871411
true,
1388-
Arc::clone(self.outdir),
13891412
LangString::empty_for_test(),
13901413
self.edition,
13911414
|_: UnusedExterns| {},
13921415
false,
1416+
// To prevent writing over an existing doctest
1417+
Some(&format!("_{}_{}", self.edition, *self.ran_edition_tests)),
1418+
out_dir,
13931419
);
13941420
if let Err(TestFailure::CompileError) = ret {
13951421
// We failed to compile all compatible tests as one so we push them into the

Diff for: tests/run-make/doctests-keep-binaries/Makefile

+4-4
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@ run:
1111
mkdir -p $(TMPDIR)/doctests
1212
$(RUSTC) --crate-type rlib t.rs
1313
$(RUSTDOC) -Zunstable-options --test --persist-doctests $(TMPDIR)/doctests --extern t=$(TMPDIR)/libt.rlib t.rs
14-
$(TMPDIR)/doctests/t_rs_2_0/rust_out
15-
$(TMPDIR)/doctests/t_rs_8_0/rust_out
14+
$(TMPDIR)/doctests/t_rs_12_0/rust_out
15+
$(TMPDIR)/doctests/rust_out_2015_0
1616
rm -rf $(TMPDIR)/doctests
1717

1818
no_run:
1919
mkdir -p $(TMPDIR)/doctests
2020
$(RUSTC) --crate-type rlib t.rs
2121
$(RUSTDOC) -Zunstable-options --test --persist-doctests $(TMPDIR)/doctests --extern t=$(TMPDIR)/libt.rlib t.rs --no-run
22-
$(TMPDIR)/doctests/t_rs_2_0/rust_out
23-
$(TMPDIR)/doctests/t_rs_8_0/rust_out
22+
$(TMPDIR)/doctests/t_rs_12_0/rust_out
23+
$(TMPDIR)/doctests/rust_out_2015_0
2424
rm -rf $(TMPDIR)/doctests
2525

2626
# Behavior with --test-run-directory with relative paths.

Diff for: tests/run-make/doctests-keep-binaries/t.rs

+8
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,12 @@ pub fn foople() {}
88
/// ```
99
/// t::florp();
1010
/// ```
11+
///
12+
/// ```
13+
/// #![no_std]
14+
///
15+
/// fn main() {
16+
/// let x = 12;
17+
/// }
18+
/// ```
1119
pub fn florp() {}

0 commit comments

Comments
 (0)