diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 89b1b4f84b6b6..62fdee987355a 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -667,6 +667,10 @@ pub struct Config { /// to avoid `!nocapture` double-negatives. pub nocapture: bool, + /// True if the experimental new output-capture implementation should be + /// used, avoiding the need for `#![feature(internal_output_capture)]`. + pub new_output_capture: bool, + /// Needed both to construct [`build_helper::git::GitConfig`]. pub nightly_branch: String, pub git_merge_commit_email: String, @@ -784,6 +788,7 @@ impl Config { builtin_cfg_names: Default::default(), supported_crate_types: Default::default(), nocapture: Default::default(), + new_output_capture: Default::default(), nightly_branch: Default::default(), git_merge_commit_email: Default::default(), profiler_runtime: Default::default(), diff --git a/src/tools/compiletest/src/executor.rs b/src/tools/compiletest/src/executor.rs index 5519ef1af1fad..b0dc24798b6cd 100644 --- a/src/tools/compiletest/src/executor.rs +++ b/src/tools/compiletest/src/executor.rs @@ -13,6 +13,7 @@ use std::sync::{Arc, Mutex, mpsc}; use std::{env, hint, io, mem, panic, thread}; use crate::common::{Config, TestPaths}; +use crate::output_capture::{self, ConsoleOut}; use crate::panic_hook; mod deadline; @@ -120,28 +121,28 @@ fn run_test_inner( runnable_test: RunnableTest, completion_sender: mpsc::Sender, ) { - let is_capture = !runnable_test.config.nocapture; + let capture = CaptureKind::for_config(&runnable_test.config); // Install a panic-capture buffer for use by the custom panic hook. - if is_capture { + if capture.should_set_panic_hook() { panic_hook::set_capture_buf(Default::default()); } - let capture_buf = is_capture.then(|| Arc::new(Mutex::new(vec![]))); - if let Some(capture_buf) = &capture_buf { - io::set_output_capture(Some(Arc::clone(capture_buf))); + if let CaptureKind::Old { ref buf } = capture { + io::set_output_capture(Some(Arc::clone(buf))); } - let panic_payload = panic::catch_unwind(move || runnable_test.run()).err(); + let stdout = capture.stdout(); + let stderr = capture.stderr(); + + let panic_payload = panic::catch_unwind(move || runnable_test.run(stdout, stderr)).err(); if let Some(panic_buf) = panic_hook::take_capture_buf() { let panic_buf = panic_buf.lock().unwrap_or_else(|e| e.into_inner()); - // For now, forward any captured panic message to (captured) stderr. - // FIXME(Zalathar): Once we have our own output-capture buffer for - // non-panic output, append the panic message to that buffer instead. - eprint!("{panic_buf}"); + // Forward any captured panic message to (captured) stderr. + write!(stderr, "{panic_buf}"); } - if is_capture { + if matches!(capture, CaptureKind::Old { .. }) { io::set_output_capture(None); } @@ -152,11 +153,70 @@ fn run_test_inner( TestOutcome::Failed { message: Some("test did not panic as expected") } } }; - let stdout = capture_buf.map(|mutex| mutex.lock().unwrap_or_else(|e| e.into_inner()).to_vec()); + let stdout = capture.into_inner(); completion_sender.send(TestCompletion { id, outcome, stdout }).unwrap(); } +enum CaptureKind { + /// Do not capture test-runner output, for `--no-capture`. + /// + /// (This does not affect `rustc` and other subprocesses spawned by test + /// runners, whose output is always captured.) + None, + + /// Use the old output-capture implementation, which relies on the unstable + /// library feature `#![feature(internal_output_capture)]`. + Old { buf: Arc>> }, + + /// Use the new output-capture implementation, which only uses stable Rust. + New { buf: output_capture::CaptureBuf }, +} + +impl CaptureKind { + fn for_config(config: &Config) -> Self { + if config.nocapture { + Self::None + } else if config.new_output_capture { + Self::New { buf: output_capture::CaptureBuf::new() } + } else { + // Create a capure buffer for `io::set_output_capture`. + Self::Old { buf: Default::default() } + } + } + + fn should_set_panic_hook(&self) -> bool { + match self { + Self::None => false, + Self::Old { .. } => true, + Self::New { .. } => true, + } + } + + fn stdout(&self) -> &dyn ConsoleOut { + self.capture_buf_or(&output_capture::Stdout) + } + + fn stderr(&self) -> &dyn ConsoleOut { + self.capture_buf_or(&output_capture::Stderr) + } + + fn capture_buf_or<'a>(&'a self, fallback: &'a dyn ConsoleOut) -> &'a dyn ConsoleOut { + match self { + Self::None | Self::Old { .. } => fallback, + Self::New { buf } => buf, + } + } + + fn into_inner(self) -> Option> { + match self { + Self::None => None, + Self::Old { buf } => Some(buf.lock().unwrap_or_else(|e| e.into_inner()).to_vec()), + Self::New { buf } => Some(buf.into_inner().into()), + } + } +} + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] struct TestId(usize); @@ -174,10 +234,12 @@ impl RunnableTest { Self { config, testpaths, revision } } - fn run(&self) { + fn run(&self, stdout: &dyn ConsoleOut, stderr: &dyn ConsoleOut) { __rust_begin_short_backtrace(|| { crate::runtest::run( Arc::clone(&self.config), + stdout, + stderr, &self.testpaths, self.revision.as_deref(), ); diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index fa84691a46f41..f647f96a9bf34 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -15,6 +15,7 @@ pub mod directives; pub mod errors; mod executor; mod json; +mod output_capture; mod panic_hook; mod raise_fd_limit; mod read2; @@ -177,6 +178,12 @@ pub fn parse_config(args: Vec) -> Config { // FIXME: Temporarily retained so we can point users to `--no-capture` .optflag("", "nocapture", "") .optflag("", "no-capture", "don't capture stdout/stderr of tests") + .optopt( + "N", + "new-output-capture", + "enables or disables the new output-capture implementation", + "off|on", + ) .optflag("", "profiler-runtime", "is the profiler runtime enabled for this target") .optflag("h", "help", "show this message") .reqopt("", "channel", "current Rust channel", "CHANNEL") @@ -461,6 +468,14 @@ pub fn parse_config(args: Vec) -> Config { supported_crate_types: OnceLock::new(), nocapture: matches.opt_present("no-capture"), + new_output_capture: { + let value = matches + .opt_str("new-output-capture") + .or_else(|| env::var("COMPILETEST_NEW_OUTPUT_CAPTURE").ok()) + .unwrap_or_else(|| "off".to_owned()); + parse_bool_option(&value) + .unwrap_or_else(|| panic!("unknown `--new-output-capture` value `{value}` given")) + }, nightly_branch: matches.opt_str("nightly-branch").unwrap(), git_merge_commit_email: matches.opt_str("git-merge-commit-email").unwrap(), @@ -476,6 +491,19 @@ pub fn parse_config(args: Vec) -> Config { } } +/// Parses the same set of boolean values accepted by rustc command-line arguments. +/// +/// Accepting all of these values is more complicated than just picking one +/// pair, but has the advantage that contributors who are used to rustc +/// shouldn't have to think about which values are legal. +fn parse_bool_option(value: &str) -> Option { + match value { + "off" | "no" | "n" | "false" => Some(false), + "on" | "yes" | "y" | "true" => Some(true), + _ => None, + } +} + pub fn opt_str(maybestr: &Option) -> &str { match *maybestr { None => "(none)", diff --git a/src/tools/compiletest/src/output_capture.rs b/src/tools/compiletest/src/output_capture.rs new file mode 100644 index 0000000000000..de1aea11ade9b --- /dev/null +++ b/src/tools/compiletest/src/output_capture.rs @@ -0,0 +1,52 @@ +use std::fmt; +use std::panic::RefUnwindSafe; +use std::sync::Mutex; + +pub trait ConsoleOut: fmt::Debug + RefUnwindSafe { + fn write_fmt(&self, args: fmt::Arguments<'_>); +} + +#[derive(Debug)] +pub(crate) struct Stdout; + +impl ConsoleOut for Stdout { + fn write_fmt(&self, args: fmt::Arguments<'_>) { + print!("{args}"); + } +} + +#[derive(Debug)] +pub(crate) struct Stderr; + +impl ConsoleOut for Stderr { + fn write_fmt(&self, args: fmt::Arguments<'_>) { + eprint!("{args}"); + } +} + +pub(crate) struct CaptureBuf { + inner: Mutex, +} + +impl CaptureBuf { + pub(crate) fn new() -> Self { + Self { inner: Mutex::new(String::new()) } + } + + pub(crate) fn into_inner(self) -> String { + self.inner.into_inner().unwrap_or_else(|e| e.into_inner()) + } +} + +impl fmt::Debug for CaptureBuf { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("CaptureBuf").finish_non_exhaustive() + } +} + +impl ConsoleOut for CaptureBuf { + fn write_fmt(&self, args: fmt::Arguments<'_>) { + let mut s = self.inner.lock().unwrap_or_else(|e| e.into_inner()); + ::write_fmt(&mut s, args).unwrap(); + } +} diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 867624cc8fa97..89fb8eb4357b7 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -23,6 +23,7 @@ use crate::common::{ }; use crate::directives::TestProps; use crate::errors::{Error, ErrorKind, load_errors}; +use crate::output_capture::ConsoleOut; use crate::read2::{Truncated, read2_abbreviated}; use crate::runtest::compute_diff::{DiffLine, make_diff, write_diff, write_filtered_diff}; use crate::util::{Utf8PathBufExt, add_dylib_path, static_regex}; @@ -108,7 +109,13 @@ fn dylib_name(name: &str) -> String { format!("{}{name}.{}", std::env::consts::DLL_PREFIX, std::env::consts::DLL_EXTENSION) } -pub fn run(config: Arc, testpaths: &TestPaths, revision: Option<&str>) { +pub fn run( + config: Arc, + stdout: &dyn ConsoleOut, + stderr: &dyn ConsoleOut, + testpaths: &TestPaths, + revision: Option<&str>, +) { match &*config.target { "arm-linux-androideabi" | "armv7-linux-androideabi" @@ -131,7 +138,7 @@ pub fn run(config: Arc, testpaths: &TestPaths, revision: Option<&str>) { if config.verbose { // We're going to be dumping a lot of info. Start on a new line. - print!("\n\n"); + write!(stdout, "\n\n"); } debug!("running {}", testpaths.file); let mut props = TestProps::from_file(&testpaths.file, revision, &config); @@ -143,7 +150,7 @@ pub fn run(config: Arc, testpaths: &TestPaths, revision: Option<&str>) { props.incremental_dir = Some(incremental_dir(&config, testpaths, revision)); } - let cx = TestCx { config: &config, props: &props, testpaths, revision }; + let cx = TestCx { config: &config, stdout, stderr, props: &props, testpaths, revision }; if let Err(e) = create_dir_all(&cx.output_base_dir()) { panic!("failed to create output base directory {}: {e}", cx.output_base_dir()); @@ -162,6 +169,8 @@ pub fn run(config: Arc, testpaths: &TestPaths, revision: Option<&str>) { revision_props.incremental_dir = props.incremental_dir.clone(); let rev_cx = TestCx { config: &config, + stdout, + stderr, props: &revision_props, testpaths, revision: Some(revision), @@ -212,6 +221,8 @@ pub fn compute_stamp_hash(config: &Config) -> String { #[derive(Copy, Clone, Debug)] struct TestCx<'test> { config: &'test Config, + stdout: &'test dyn ConsoleOut, + stderr: &'test dyn ConsoleOut, props: &'test TestProps, testpaths: &'test TestPaths, revision: Option<&'test str>, @@ -603,7 +614,8 @@ impl<'test> TestCx<'test> { ); } else { for pattern in missing_patterns { - println!( + writeln!( + self.stdout, "\n{prefix}: error pattern '{pattern}' not found!", prefix = self.error_prefix() ); @@ -783,7 +795,8 @@ impl<'test> TestCx<'test> { }; format!("{file_name}:{line_num}{opt_col_num}") }; - let print_error = |e| println!("{}: {}: {}", line_str(e), e.kind, e.msg.cyan()); + let print_error = + |e| writeln!(self.stdout, "{}: {}: {}", line_str(e), e.kind, e.msg.cyan()); let push_suggestion = |suggestions: &mut Vec<_>, e: &Error, kind, line, msg, color, rank| { let mut ret = String::new(); @@ -811,7 +824,7 @@ impl<'test> TestCx<'test> { if let Some(&(_, top_rank)) = suggestions.first() { for (suggestion, rank) in suggestions { if rank == top_rank { - println!(" {} {suggestion}", prefix.color(color)); + writeln!(self.stdout, " {} {suggestion}", prefix.color(color)); } } } @@ -824,7 +837,8 @@ impl<'test> TestCx<'test> { // - only known line - meh, but suggested // - others are not worth suggesting if !unexpected.is_empty() { - println!( + writeln!( + self.stdout, "\n{prefix}: {n} diagnostics reported in JSON output but not expected in test file", prefix = self.error_prefix(), n = unexpected.len(), @@ -858,7 +872,8 @@ impl<'test> TestCx<'test> { } } if !not_found.is_empty() { - println!( + writeln!( + self.stdout, "\n{prefix}: {n} diagnostics expected in test file but not reported in JSON output", prefix = self.error_prefix(), n = not_found.len(), @@ -978,6 +993,8 @@ impl<'test> TestCx<'test> { self.props.from_aux_file(&aux_testpaths.file, self.revision, self.config); let aux_cx = TestCx { config: self.config, + stdout: self.stdout, + stderr: self.stderr, props: &props_for_aux, testpaths: &aux_testpaths, revision: self.revision, @@ -1343,6 +1360,8 @@ impl<'test> TestCx<'test> { let aux_output = TargetLocation::ThisDirectory(aux_dir.clone()); let aux_cx = TestCx { config: self.config, + stdout: self.stdout, + stderr: self.stderr, props: &aux_props, testpaths: &aux_testpaths, revision: self.revision, @@ -1948,11 +1967,11 @@ impl<'test> TestCx<'test> { } else { path.file_name().unwrap().into() }; - println!("------{proc_name} stdout------------------------------"); - println!("{}", out); - println!("------{proc_name} stderr------------------------------"); - println!("{}", err); - println!("------------------------------------------"); + writeln!(self.stdout, "------{proc_name} stdout------------------------------"); + writeln!(self.stdout, "{}", out); + writeln!(self.stdout, "------{proc_name} stderr------------------------------"); + writeln!(self.stdout, "{}", err); + writeln!(self.stdout, "------------------------------------------"); } fn dump_output_file(&self, out: &str, extension: &str) { @@ -2014,7 +2033,7 @@ impl<'test> TestCx<'test> { debug!("{message}"); if self.config.verbose { // Note: `./x test ... --verbose --no-capture` is needed to see this print. - println!("{message}"); + writeln!(self.stdout, "{message}"); } } @@ -2030,7 +2049,7 @@ impl<'test> TestCx<'test> { #[track_caller] fn fatal(&self, err: &str) -> ! { - println!("\n{prefix}: {err}", prefix = self.error_prefix()); + writeln!(self.stdout, "\n{prefix}: {err}", prefix = self.error_prefix()); error!("fatal error, panic: {:?}", err); panic!("fatal error"); } @@ -2048,15 +2067,15 @@ impl<'test> TestCx<'test> { proc_res: &ProcRes, callback_before_unwind: impl FnOnce(), ) -> ! { - println!("\n{prefix}: {err}", prefix = self.error_prefix()); + writeln!(self.stdout, "\n{prefix}: {err}", prefix = self.error_prefix()); // Some callers want to print additional notes after the main error message. if let Some(note) = extra_note { - println!("{note}"); + writeln!(self.stdout, "{note}"); } // Print the details and output of the subprocess that caused this test to fail. - println!("{}", proc_res.format_info()); + writeln!(self.stdout, "{}", proc_res.format_info()); // Some callers want print more context or show a custom diff before the unwind occurs. callback_before_unwind(); @@ -2126,7 +2145,7 @@ impl<'test> TestCx<'test> { if !self.config.has_html_tidy { return; } - println!("info: generating a diff against nightly rustdoc"); + writeln!(self.stdout, "info: generating a diff against nightly rustdoc"); let suffix = self.safe_revision().map_or("nightly".into(), |path| path.to_owned() + "-nightly"); @@ -2162,7 +2181,7 @@ impl<'test> TestCx<'test> { let proc_res = new_rustdoc.document(&compare_dir, &new_rustdoc.testpaths); if !proc_res.status.success() { - eprintln!("failed to run nightly rustdoc"); + writeln!(self.stderr, "failed to run nightly rustdoc"); return; } @@ -2207,6 +2226,7 @@ impl<'test> TestCx<'test> { let diff_filename = format!("build/tmp/rustdoc-compare-{}.diff", std::process::id()); if !write_filtered_diff( + self, &diff_filename, out_dir, &compare_dir, @@ -2227,7 +2247,7 @@ impl<'test> TestCx<'test> { if let Some(pager) = pager { let pager = pager.trim(); if self.config.verbose { - eprintln!("using pager {}", pager); + writeln!(self.stderr, "using pager {}", pager); } let output = Command::new(pager) // disable paging; we want this to be non-interactive @@ -2238,8 +2258,8 @@ impl<'test> TestCx<'test> { .output() .unwrap(); assert!(output.status.success()); - println!("{}", String::from_utf8_lossy(&output.stdout)); - eprintln!("{}", String::from_utf8_lossy(&output.stderr)); + writeln!(self.stdout, "{}", String::from_utf8_lossy(&output.stdout)); + writeln!(self.stderr, "{}", String::from_utf8_lossy(&output.stderr)); } else { warning!("no pager configured, falling back to unified diff"); help!( @@ -2254,7 +2274,7 @@ impl<'test> TestCx<'test> { match diff.read_until(b'\n', &mut line) { Ok(0) => break, Ok(_) => {} - Err(e) => eprintln!("ERROR: {:?}", e), + Err(e) => writeln!(self.stderr, "ERROR: {:?}", e), } match String::from_utf8(line.clone()) { Ok(line) => { @@ -2802,11 +2822,11 @@ impl<'test> TestCx<'test> { if let Err(err) = fs::write(&actual_path, &actual) { self.fatal(&format!("failed to write {stream} to `{actual_path}`: {err}",)); } - println!("Saved the actual {stream} to `{actual_path}`"); + writeln!(self.stdout, "Saved the actual {stream} to `{actual_path}`"); if !self.config.bless { if expected.is_empty() { - println!("normalized {}:\n{}\n", stream, actual); + writeln!(self.stdout, "normalized {}:\n{}\n", stream, actual); } else { self.show_diff( stream, @@ -2830,14 +2850,15 @@ impl<'test> TestCx<'test> { if let Err(err) = fs::write(&expected_path, &actual) { self.fatal(&format!("failed to write {stream} to `{expected_path}`: {err}")); } - println!( + writeln!( + self.stdout, "Blessing the {stream} of `{test_name}` as `{expected_path}`", test_name = self.testpaths.file ); } } - println!("\nThe actual {stream} differed from the expected {stream}"); + writeln!(self.stdout, "\nThe actual {stream} differed from the expected {stream}"); if self.config.bless { CompareOutcome::Blessed } else { CompareOutcome::Differed } } @@ -2852,7 +2873,7 @@ impl<'test> TestCx<'test> { actual: &str, actual_unnormalized: &str, ) { - eprintln!("diff of {stream}:\n"); + writeln!(self.stderr, "diff of {stream}:\n"); if let Some(diff_command) = self.config.diff_command.as_deref() { let mut args = diff_command.split_whitespace(); let name = args.next().unwrap(); @@ -2864,11 +2885,11 @@ impl<'test> TestCx<'test> { } Ok(output) => { let output = String::from_utf8_lossy(&output.stdout); - eprint!("{output}"); + write!(self.stderr, "{output}"); } } } else { - eprint!("{}", write_diff(expected, actual, 3)); + write!(self.stderr, "{}", write_diff(expected, actual, 3)); } // NOTE: argument order is important, we need `actual` to be on the left so the line number match up when we compare it to `actual_unnormalized` below. @@ -2906,9 +2927,16 @@ impl<'test> TestCx<'test> { && !mismatches_unnormalized.is_empty() && !mismatches_normalized.is_empty() { - eprintln!("Note: some mismatched output was normalized before being compared"); + writeln!( + self.stderr, + "Note: some mismatched output was normalized before being compared" + ); // FIXME: respect diff_command - eprint!("{}", write_diff(&mismatches_unnormalized, &mismatches_normalized, 0)); + write!( + self.stderr, + "{}", + write_diff(&mismatches_unnormalized, &mismatches_normalized, 0) + ); } } @@ -2986,7 +3014,7 @@ impl<'test> TestCx<'test> { fs::create_dir_all(&incremental_dir).unwrap(); if self.config.verbose { - println!("init_incremental_test: incremental_dir={incremental_dir}"); + writeln!(self.stdout, "init_incremental_test: incremental_dir={incremental_dir}"); } } } diff --git a/src/tools/compiletest/src/runtest/codegen_units.rs b/src/tools/compiletest/src/runtest/codegen_units.rs index 44ddcb1d28882..16c251c3c9e24 100644 --- a/src/tools/compiletest/src/runtest/codegen_units.rs +++ b/src/tools/compiletest/src/runtest/codegen_units.rs @@ -62,13 +62,13 @@ impl TestCx<'_> { if !missing.is_empty() { missing.sort(); - println!("\nThese items should have been contained but were not:\n"); + writeln!(self.stdout, "\nThese items should have been contained but were not:\n"); for item in &missing { - println!("{}", item); + writeln!(self.stdout, "{}", item); } - println!("\n"); + writeln!(self.stdout, "\n"); } if !unexpected.is_empty() { @@ -78,24 +78,32 @@ impl TestCx<'_> { sorted }; - println!("\nThese items were contained but should not have been:\n"); + writeln!(self.stdout, "\nThese items were contained but should not have been:\n"); for item in sorted { - println!("{}", item); + writeln!(self.stdout, "{}", item); } - println!("\n"); + writeln!(self.stdout, "\n"); } if !wrong_cgus.is_empty() { wrong_cgus.sort_by_key(|pair| pair.0.name.clone()); - println!("\nThe following items were assigned to wrong codegen units:\n"); + writeln!(self.stdout, "\nThe following items were assigned to wrong codegen units:\n"); for &(ref expected_item, ref actual_item) in &wrong_cgus { - println!("{}", expected_item.name); - println!(" expected: {}", codegen_units_to_str(&expected_item.codegen_units)); - println!(" actual: {}", codegen_units_to_str(&actual_item.codegen_units)); - println!(); + writeln!(self.stdout, "{}", expected_item.name); + writeln!( + self.stdout, + " expected: {}", + codegen_units_to_str(&expected_item.codegen_units) + ); + writeln!( + self.stdout, + " actual: {}", + codegen_units_to_str(&actual_item.codegen_units) + ); + writeln!(self.stdout); } } diff --git a/src/tools/compiletest/src/runtest/compute_diff.rs b/src/tools/compiletest/src/runtest/compute_diff.rs index 509e7e117039c..3363127b3ea37 100644 --- a/src/tools/compiletest/src/runtest/compute_diff.rs +++ b/src/tools/compiletest/src/runtest/compute_diff.rs @@ -3,6 +3,8 @@ use std::fs::{File, FileType}; use camino::Utf8Path; +use crate::runtest::TestCx; + #[derive(Debug, PartialEq)] pub enum DiffLine { Context(String), @@ -112,6 +114,7 @@ pub(crate) fn write_diff(expected: &str, actual: &str, context_size: usize) -> S /// /// Returns whether any data was actually written. pub(crate) fn write_filtered_diff( + cx: &TestCx<'_>, diff_filename: &str, out_dir: &Utf8Path, compare_dir: &Utf8Path, @@ -147,11 +150,11 @@ where } if !wrote_data { - println!("note: diff is identical to nightly rustdoc"); + writeln!(cx.stdout, "note: diff is identical to nightly rustdoc"); assert!(diff_output.metadata().unwrap().len() == 0); return false; } else if verbose { - eprintln!("printing diff:"); + writeln!(cx.stderr, "printing diff:"); let mut buf = Vec::new(); diff_output.read_to_end(&mut buf).unwrap(); std::io::stderr().lock().write_all(&mut buf).unwrap(); diff --git a/src/tools/compiletest/src/runtest/crashes.rs b/src/tools/compiletest/src/runtest/crashes.rs index da1e74b4a56bc..0aae7eaa39cd5 100644 --- a/src/tools/compiletest/src/runtest/crashes.rs +++ b/src/tools/compiletest/src/runtest/crashes.rs @@ -6,10 +6,10 @@ impl TestCx<'_> { let proc_res = self.compile_test(WillExecute::No, self.should_emit_metadata(pm)); if std::env::var("COMPILETEST_VERBOSE_CRASHES").is_ok() { - eprintln!("{}", proc_res.status); - eprintln!("{}", proc_res.stdout); - eprintln!("{}", proc_res.stderr); - eprintln!("{}", proc_res.cmdline); + writeln!(self.stderr, "{}", proc_res.status); + writeln!(self.stderr, "{}", proc_res.stdout); + writeln!(self.stderr, "{}", proc_res.stderr); + writeln!(self.stderr, "{}", proc_res.cmdline); } // if a test does not crash, consider it an error diff --git a/src/tools/compiletest/src/runtest/debuginfo.rs b/src/tools/compiletest/src/runtest/debuginfo.rs index 88d022b8bbaaf..071c0863b7e9f 100644 --- a/src/tools/compiletest/src/runtest/debuginfo.rs +++ b/src/tools/compiletest/src/runtest/debuginfo.rs @@ -245,7 +245,7 @@ impl TestCx<'_> { cmdline, }; if adb.kill().is_err() { - println!("Adb process is already finished."); + writeln!(self.stdout, "Adb process is already finished."); } } else { let rust_pp_module_abs_path = self.config.src_root.join("src").join("etc"); @@ -256,7 +256,11 @@ impl TestCx<'_> { match self.config.gdb_version { Some(version) => { - println!("NOTE: compiletest thinks it is using GDB version {}", version); + writeln!( + self.stdout, + "NOTE: compiletest thinks it is using GDB version {}", + version + ); if !self.props.disable_gdb_pretty_printers && version > extract_gdb_version("7.4").unwrap() @@ -278,7 +282,8 @@ impl TestCx<'_> { } } _ => { - println!( + writeln!( + self.stdout, "NOTE: compiletest does not know which version of \ GDB it is using" ); @@ -376,10 +381,15 @@ impl TestCx<'_> { match self.config.lldb_version { Some(ref version) => { - println!("NOTE: compiletest thinks it is using LLDB version {}", version); + writeln!( + self.stdout, + "NOTE: compiletest thinks it is using LLDB version {}", + version + ); } _ => { - println!( + writeln!( + self.stdout, "NOTE: compiletest does not know which version of \ LLDB it is using" ); diff --git a/src/tools/compiletest/src/runtest/incremental.rs b/src/tools/compiletest/src/runtest/incremental.rs index 90cff6bab4dc6..44eb80300c394 100644 --- a/src/tools/compiletest/src/runtest/incremental.rs +++ b/src/tools/compiletest/src/runtest/incremental.rs @@ -30,7 +30,7 @@ impl TestCx<'_> { assert!(incremental_dir.exists(), "init_incremental_test failed to create incremental dir"); if self.config.verbose { - print!("revision={:?} props={:#?}", revision, self.props); + write!(self.stdout, "revision={:?} props={:#?}", revision, self.props); } if revision.starts_with("cpass") { diff --git a/src/tools/compiletest/src/runtest/mir_opt.rs b/src/tools/compiletest/src/runtest/mir_opt.rs index 55043bf4bc26d..9448792638346 100644 --- a/src/tools/compiletest/src/runtest/mir_opt.rs +++ b/src/tools/compiletest/src/runtest/mir_opt.rs @@ -80,7 +80,7 @@ impl TestCx<'_> { } let expected_string = fs::read_to_string(&expected_file).unwrap(); if dumped_string != expected_string { - print!("{}", write_diff(&expected_string, &dumped_string, 3)); + write!(self.stdout, "{}", write_diff(&expected_string, &dumped_string, 3)); panic!( "Actual MIR output differs from expected MIR output {}", expected_file.display() diff --git a/src/tools/compiletest/src/runtest/rustdoc_json.rs b/src/tools/compiletest/src/runtest/rustdoc_json.rs index 083398f927455..b8da6e2ac5280 100644 --- a/src/tools/compiletest/src/runtest/rustdoc_json.rs +++ b/src/tools/compiletest/src/runtest/rustdoc_json.rs @@ -30,8 +30,8 @@ impl TestCx<'_> { if !res.status.success() { self.fatal_proc_rec_general("jsondocck failed!", None, &res, || { - println!("Rustdoc Output:"); - println!("{}", proc_res.format_info()); + writeln!(self.stdout, "Rustdoc Output:"); + writeln!(self.stdout, "{}", proc_res.format_info()); }) } diff --git a/src/tools/compiletest/src/runtest/ui.rs b/src/tools/compiletest/src/runtest/ui.rs index 40b0ee0a399d4..d683a325c8666 100644 --- a/src/tools/compiletest/src/runtest/ui.rs +++ b/src/tools/compiletest/src/runtest/ui.rs @@ -115,10 +115,14 @@ impl TestCx<'_> { } if errors > 0 { - println!("To update references, rerun the tests and pass the `--bless` flag"); + writeln!( + self.stdout, + "To update references, rerun the tests and pass the `--bless` flag" + ); let relative_path_to_file = self.testpaths.relative_dir.join(self.testpaths.file.file_name().unwrap()); - println!( + writeln!( + self.stdout, "To only update this specific test, also pass `--test-args {}`", relative_path_to_file, );