From d01f463203a32285b2afb7a417f8e16a93e18e4a Mon Sep 17 00:00:00 2001 From: Alexander Potashev Date: Thu, 28 Mar 2024 20:50:21 +0100 Subject: [PATCH] At test discovery, write to logfile in the same format as to stdout. Example of affected command: ``` cargo test -- --logfile=/tmp/1.log --list ``` --- library/test/src/console.rs | 65 ++++++++++++++++++++----------------- library/test/src/tests.rs | 2 +- 2 files changed, 36 insertions(+), 31 deletions(-) diff --git a/library/test/src/console.rs b/library/test/src/console.rs index ac75c7936c22a..0a809e9f18092 100644 --- a/library/test/src/console.rs +++ b/library/test/src/console.rs @@ -3,6 +3,7 @@ use std::fs::File; use std::io; use std::io::prelude::Write; +use std::path::PathBuf; use std::time::Instant; use std::vec; @@ -73,6 +74,33 @@ struct OutputMultiplexer { pub outputs: Vec>, } +impl OutputMultiplexer { + pub fn new(lock_stdout: bool, logfile: &Option) -> io::Result { + let mut outputs: Vec> = vec![]; + + if lock_stdout { + let output = match term::stdout() { + None => OutputLocation::Raw(io::stdout().lock()), + Some(t) => OutputLocation::Pretty(t), + }; + outputs.push(Box::new(output)) + } else { + let output = match term::stdout() { + None => OutputLocation::Raw(io::stdout()), + Some(t) => OutputLocation::Pretty(t), + }; + outputs.push(Box::new(output)) + } + + match logfile { + Some(ref path) => outputs.push(Box::new(OutputLocation::Raw(File::create(path)?))), + None => (), + }; + + Ok(Self { outputs }) + } +} + impl Output for OutputMultiplexer { fn write_pretty(&mut self, word: &str, color: term::color::Color) -> io::Result<()> { for output in &mut self.outputs { @@ -92,33 +120,14 @@ impl Output for OutputMultiplexer { } pub struct ConsoleTestDiscoveryState { - log_out: OutputMultiplexer, pub tests: usize, pub benchmarks: usize, pub ignored: usize, } impl ConsoleTestDiscoveryState { - pub fn new(opts: &TestOpts) -> io::Result { - let mut log_out = OutputMultiplexer { outputs: vec![] }; - match opts.logfile { - Some(ref path) => { - log_out.outputs.push(Box::new(OutputLocation::Raw(File::create(path)?))) - } - None => (), - }; - - Ok(ConsoleTestDiscoveryState { log_out, tests: 0, benchmarks: 0, ignored: 0 }) - } - - pub fn write_log(&mut self, msg: F) -> io::Result<()> - where - S: AsRef, - F: FnOnce() -> S, - { - let msg = msg(); - let msg = msg.as_ref(); - self.log_out.write_plain(msg) + pub fn new() -> io::Result { + Ok(ConsoleTestDiscoveryState { tests: 0, benchmarks: 0, ignored: 0 }) } } @@ -219,19 +228,16 @@ impl ConsoleTestState { // List the tests to console, and optionally to logfile. Filters are honored. pub fn list_tests_console(opts: &TestOpts, tests: Vec) -> io::Result<()> { - let mut output = match term::stdout() { - None => OutputLocation::Raw(io::stdout().lock()), - Some(t) => OutputLocation::Pretty(t), - }; + let mut st = ConsoleTestDiscoveryState::new()?; + let mut multiplexer = OutputMultiplexer::new(true, &opts.logfile)?; let mut out: Box = match opts.format { OutputFormat::Pretty | OutputFormat::Junit => { - Box::new(PrettyFormatter::new(&mut output, false, 0, false, None)) + Box::new(PrettyFormatter::new(&mut multiplexer, false, 0, false, None)) } - OutputFormat::Terse => Box::new(TerseFormatter::new(&mut output, false, 0, false)), - OutputFormat::Json => Box::new(JsonFormatter::new(&mut output)), + OutputFormat::Terse => Box::new(TerseFormatter::new(&mut multiplexer, false, 0, false)), + OutputFormat::Json => Box::new(JsonFormatter::new(&mut multiplexer)), }; - let mut st = ConsoleTestDiscoveryState::new(opts)?; out.write_discovery_start()?; for test in filter_tests(opts, tests).into_iter() { @@ -253,7 +259,6 @@ pub fn list_tests_console(opts: &TestOpts, tests: Vec) -> io::Res st.ignored += if desc.ignore { 1 } else { 0 }; out.write_test_discovered(&desc, fntype)?; - st.write_log(|| format!("{fntype} {}\n", desc.name))?; } out.write_discovery_finish(&st) diff --git a/library/test/src/tests.rs b/library/test/src/tests.rs index fc96a06549162..005cabd3c3885 100644 --- a/library/test/src/tests.rs +++ b/library/test/src/tests.rs @@ -994,7 +994,7 @@ fn test_discovery_logfile_format() { // Split output at line breaks to make the comparison platform-agnostic regarding newline style. let contents_lines = contents.as_str().lines().collect::>(); - assert_eq!(contents_lines, vec!["test whatever"]); + assert_eq!(contents_lines, vec!["whatever: test", "", "1 test, 0 benchmarks"]); } #[test]