Skip to content

Commit 0dc72d9

Browse files
camelidGuillaumeGomez
authored andcommitted
Make doctests before running them; reintroduce RunnableDoctest
1 parent 366000d commit 0dc72d9

File tree

1 file changed

+54
-42
lines changed

1 file changed

+54
-42
lines changed

Diff for: src/librustdoc/doctest.rs

+54-42
Original file line numberDiff line numberDiff line change
@@ -369,57 +369,59 @@ fn wrapped_rustc_command(rustc_wrappers: &[PathBuf], rustc_binary: &Path) -> Com
369369
command
370370
}
371371

372+
struct RunnableDoctest {
373+
full_test_code: String,
374+
full_test_line_offset: usize,
375+
test_opts: IndividualTestOptions,
376+
global_opts: GlobalTestOptions,
377+
scraped_test: ScrapedDoctest,
378+
}
379+
372380
fn run_test(
373-
test: &str,
374-
line: usize,
381+
doctest: RunnableDoctest,
375382
rustdoc_options: &RustdocOptions,
376-
test_options: IndividualTestOptions,
377-
mut lang_string: LangString,
378-
no_run: bool,
379-
opts: &GlobalTestOptions,
380-
edition: Edition,
383+
supports_color: bool,
381384
report_unused_externs: impl Fn(UnusedExterns),
382385
) -> Result<(), TestFailure> {
383-
let (test, line_offset, supports_color) = make_test(
384-
test,
385-
Some(&opts.crate_name),
386-
lang_string.test_harness,
387-
opts,
388-
edition,
389-
Some(&test_options.test_id),
390-
);
391-
386+
let scraped_test = &doctest.scraped_test;
387+
let langstr = &scraped_test.langstr;
392388
// Make sure we emit well-formed executable names for our target.
393389
let rust_out = add_exe_suffix("rust_out".to_owned(), &rustdoc_options.target);
394-
let output_file = test_options.outdir.path().join(rust_out);
390+
let output_file = doctest.test_opts.outdir.path().join(rust_out);
395391

396392
let rustc_binary = rustdoc_options
397393
.test_builder
398394
.as_deref()
399395
.unwrap_or_else(|| rustc_interface::util::rustc_path().expect("found rustc"));
400396
let mut compiler = wrapped_rustc_command(&rustdoc_options.test_builder_wrappers, rustc_binary);
401397

402-
compiler.arg(&format!("@{}", opts.args_file.display()));
398+
compiler.arg(&format!("@{}", doctest.global_opts.args_file.display()));
403399

404400
if let Some(sysroot) = &rustdoc_options.maybe_sysroot {
405401
compiler.arg(format!("--sysroot={}", sysroot.display()));
406402
}
407403

408-
compiler.arg("--edition").arg(&edition.to_string());
409-
compiler.env("UNSTABLE_RUSTDOC_TEST_PATH", &test_options.path);
410-
compiler.env("UNSTABLE_RUSTDOC_TEST_LINE", format!("{}", line as isize - line_offset as isize));
404+
compiler.arg("--edition").arg(&scraped_test.edition(rustdoc_options).to_string());
405+
compiler.env("UNSTABLE_RUSTDOC_TEST_PATH", &doctest.test_opts.path);
406+
compiler.env(
407+
"UNSTABLE_RUSTDOC_TEST_LINE",
408+
format!("{}", scraped_test.line as isize - doctest.full_test_line_offset as isize),
409+
);
411410
compiler.arg("-o").arg(&output_file);
412-
if lang_string.test_harness {
411+
if langstr.test_harness {
413412
compiler.arg("--test");
414413
}
415-
if rustdoc_options.json_unused_externs.is_enabled() && !lang_string.compile_fail {
414+
if rustdoc_options.json_unused_externs.is_enabled() && !langstr.compile_fail {
416415
compiler.arg("--error-format=json");
417416
compiler.arg("--json").arg("unused-externs");
418417
compiler.arg("-W").arg("unused_crate_dependencies");
419418
compiler.arg("-Z").arg("unstable-options");
420419
}
421420

422-
if no_run && !lang_string.compile_fail && rustdoc_options.persist_doctests.is_none() {
421+
if scraped_test.no_run(rustdoc_options)
422+
&& !langstr.compile_fail
423+
&& rustdoc_options.persist_doctests.is_none()
424+
{
423425
// FIXME: why does this code check if it *shouldn't* persist doctests
424426
// -- shouldn't it be the negation?
425427
compiler.arg("--emit=metadata");
@@ -459,7 +461,7 @@ fn run_test(
459461
let mut child = compiler.spawn().expect("Failed to spawn rustc process");
460462
{
461463
let stdin = child.stdin.as_mut().expect("Failed to open stdin");
462-
stdin.write_all(test.as_bytes()).expect("could write out test sources");
464+
stdin.write_all(doctest.full_test_code.as_bytes()).expect("could write out test sources");
463465
}
464466
let output = child.wait_with_output().expect("Failed to read stdout");
465467

@@ -490,20 +492,26 @@ fn run_test(
490492
}
491493

492494
let _bomb = Bomb(&out);
493-
match (output.status.success(), lang_string.compile_fail) {
495+
match (output.status.success(), langstr.compile_fail) {
494496
(true, true) => {
495497
return Err(TestFailure::UnexpectedCompilePass);
496498
}
497499
(true, false) => {}
498500
(false, true) => {
499-
if !lang_string.error_codes.is_empty() {
501+
if !langstr.error_codes.is_empty() {
500502
// We used to check if the output contained "error[{}]: " but since we added the
501503
// colored output, we can't anymore because of the color escape characters before
502504
// the ":".
503-
lang_string.error_codes.retain(|err| !out.contains(&format!("error[{err}]")));
504-
505-
if !lang_string.error_codes.is_empty() {
506-
return Err(TestFailure::MissingErrorCodes(lang_string.error_codes));
505+
let missing_codes: Vec<String> = scraped_test
506+
.langstr
507+
.error_codes
508+
.iter()
509+
.filter(|err| !out.contains(&format!("error[{err}]")))
510+
.cloned()
511+
.collect();
512+
513+
if !missing_codes.is_empty() {
514+
return Err(TestFailure::MissingErrorCodes(missing_codes));
507515
}
508516
}
509517
}
@@ -512,7 +520,7 @@ fn run_test(
512520
}
513521
}
514522

515-
if no_run {
523+
if scraped_test.no_run(rustdoc_options) {
516524
return Ok(());
517525
}
518526

@@ -544,9 +552,9 @@ fn run_test(
544552
match result {
545553
Err(e) => return Err(TestFailure::ExecutionError(e)),
546554
Ok(out) => {
547-
if lang_string.should_panic && out.status.success() {
555+
if langstr.should_panic && out.status.success() {
548556
return Err(TestFailure::UnexpectedRunPass);
549-
} else if !lang_string.should_panic && !out.status.success() {
557+
} else if !langstr.should_panic && !out.status.success() {
550558
return Err(TestFailure::ExecutionFailure(out));
551559
}
552560
}
@@ -1099,19 +1107,23 @@ fn doctest_run_fn(
10991107
let report_unused_externs = |uext| {
11001108
unused_externs.lock().unwrap().push(uext);
11011109
};
1102-
let no_run = scraped_test.no_run(&rustdoc_options);
11031110
let edition = scraped_test.edition(&rustdoc_options);
1104-
let res = run_test(
1111+
let (full_test_code, full_test_line_offset, supports_color) = make_test(
11051112
&scraped_test.text,
1106-
scraped_test.line,
1107-
&rustdoc_options,
1108-
test_opts,
1109-
scraped_test.langstr,
1110-
no_run,
1113+
Some(&global_opts.crate_name),
1114+
scraped_test.langstr.test_harness,
11111115
&global_opts,
11121116
edition,
1113-
report_unused_externs,
1117+
Some(&test_opts.test_id),
11141118
);
1119+
let runnable_test = RunnableDoctest {
1120+
full_test_code,
1121+
full_test_line_offset,
1122+
test_opts,
1123+
global_opts,
1124+
scraped_test,
1125+
};
1126+
let res = run_test(runnable_test, &rustdoc_options, supports_color, report_unused_externs);
11151127

11161128
if let Err(err) = res {
11171129
match err {

0 commit comments

Comments
 (0)