Skip to content

Commit 94bd121

Browse files
author
Gilad Naaman
committed
libtest: Fixed pretty-printing of test names in single-threaded code.
1 parent e570e9e commit 94bd121

File tree

2 files changed

+69
-36
lines changed

2 files changed

+69
-36
lines changed

src/libtest/formatters.rs

Lines changed: 56 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
use super::*;
1212

1313
pub(crate) trait OutputFormatter {
14-
fn write_run_start(&mut self, len: usize) -> io::Result<()>;
15-
fn write_test_start(&mut self, test: &TestDesc) -> io::Result<()>;
14+
fn write_run_start(&mut self, test_count: usize) -> io::Result<()>;
15+
fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()>;
1616
fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()>;
1717
fn write_result(&mut self,
1818
desc: &TestDesc,
@@ -26,17 +26,26 @@ pub(crate) struct HumanFormatter<T> {
2626
terse: bool,
2727
use_color: bool,
2828
test_count: usize,
29-
max_name_len: usize, // number of columns to fill when aligning names
29+
30+
/// Number of columns to fill when aligning names
31+
max_name_len: usize,
32+
33+
is_multithreaded: bool,
3034
}
3135

3236
impl<T: Write> HumanFormatter<T> {
33-
pub fn new(out: OutputLocation<T>, use_color: bool, terse: bool, max_name_len: usize) -> Self {
37+
pub fn new(out: OutputLocation<T>,
38+
use_color: bool,
39+
terse: bool,
40+
max_name_len: usize,
41+
is_multithreaded: bool) -> Self {
3442
HumanFormatter {
3543
out,
3644
terse,
3745
use_color,
3846
test_count: 0,
3947
max_name_len,
48+
is_multithreaded,
4049
}
4150
}
4251

@@ -160,28 +169,42 @@ impl<T: Write> HumanFormatter<T> {
160169
}
161170
Ok(())
162171
}
172+
173+
fn write_test_name(&mut self, desc: &TestDesc) -> io::Result<()> {
174+
if !(self.terse && desc.name.padding() != PadOnRight) {
175+
let name = desc.padded_name(self.max_name_len, desc.name.padding());
176+
self.write_plain(&format!("test {} ... ", name))?;
177+
}
178+
179+
Ok(())
180+
}
163181
}
164182

165183
impl<T: Write> OutputFormatter for HumanFormatter<T> {
166-
fn write_run_start(&mut self, len: usize) -> io::Result<()> {
167-
let noun = if len != 1 {
184+
fn write_run_start(&mut self, test_count: usize) -> io::Result<()> {
185+
let noun = if test_count != 1 {
168186
"tests"
169187
} else {
170188
"test"
171189
};
172-
self.write_plain(&format!("\nrunning {} {}\n", len, noun))
190+
self.write_plain(&format!("\nrunning {} {}\n", test_count, noun))
173191
}
174192

175-
fn write_test_start(&mut self, _desc: &TestDesc) -> io::Result<()> {
176-
// Do not print header, as priting it at this point will result in
177-
// an unreadable output when running tests concurrently.
193+
fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()> {
194+
// When running tests concurrently, we should not print
195+
// the test's name as the result will be mis-aligned.
196+
// When running the tests serially, we print the name here so
197+
// that the user can see which test hangs.
198+
if !self.is_multithreaded {
199+
self.write_test_name(desc)?;
200+
}
201+
178202
Ok(())
179203
}
180204

181205
fn write_result(&mut self, desc: &TestDesc, result: &TestResult, _: &[u8]) -> io::Result<()> {
182-
if !(self.terse && desc.name.padding() != PadOnRight) {
183-
let name = desc.padded_name(self.max_name_len, desc.name.padding());
184-
self.write_plain(&format!("test {} ... ", name))?;
206+
if self.is_multithreaded {
207+
self.write_test_name(desc)?;
185208
}
186209

187210
match *result {
@@ -197,6 +220,10 @@ impl<T: Write> OutputFormatter for HumanFormatter<T> {
197220
}
198221

199222
fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> {
223+
if self.is_multithreaded {
224+
self.write_test_name(desc)?;
225+
}
226+
200227
self.write_plain(&format!("test {} has been running for over {} seconds\n",
201228
desc.name,
202229
TEST_WARN_TIMEOUT_S))
@@ -251,13 +278,14 @@ pub(crate) struct JsonFormatter<T> {
251278

252279
impl<T: Write> JsonFormatter<T> {
253280
pub fn new(out: OutputLocation<T>) -> Self {
254-
Self {
255-
out, }
281+
Self { out }
256282
}
257283

258-
fn write_str<S: AsRef<str>>(&mut self, s: S) -> io::Result<()> {
259-
self.out.write_all(s.as_ref().as_ref())?;
260-
self.out.write_all("\n".as_ref())
284+
fn write_message(&mut self, s: &str) -> io::Result<()> {
285+
assert!(!s.contains('\n'));
286+
287+
self.out.write_all(s.as_ref())?;
288+
self.out.write_all(b"\n")
261289
}
262290

263291
fn write_event(&mut self,
@@ -266,14 +294,14 @@ impl<T: Write> JsonFormatter<T> {
266294
evt: &str,
267295
extra: Option<String>) -> io::Result<()> {
268296
if let Some(extras) = extra {
269-
self.write_str(&*format!(r#"{{ "type": "{}", "name": "{}", "event": "{}", {} }}"#,
297+
self.write_message(&*format!(r#"{{ "type": "{}", "name": "{}", "event": "{}", {} }}"#,
270298
ty,
271299
name,
272300
evt,
273301
extras))
274302
}
275303
else {
276-
self.write_str(&*format!(r#"{{ "type": "{}", "name": "{}", "event": "{}" }}"#,
304+
self.write_message(&*format!(r#"{{ "type": "{}", "name": "{}", "event": "{}" }}"#,
277305
ty,
278306
name,
279307
evt))
@@ -282,13 +310,14 @@ impl<T: Write> JsonFormatter<T> {
282310
}
283311

284312
impl<T: Write> OutputFormatter for JsonFormatter<T> {
285-
fn write_run_start(&mut self, len: usize) -> io::Result<()> {
286-
self.write_str(
287-
&*format!(r#"{{ "type": "suite", "event": "started", "test_count": "{}" }}"#, len))
313+
fn write_run_start(&mut self, test_count: usize) -> io::Result<()> {
314+
self.write_message(
315+
&*format!(r#"{{ "type": "suite", "event": "started", "test_count": "{}" }}"#,
316+
test_count))
288317
}
289318

290319
fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()> {
291-
self.write_str(&*format!(r#"{{ "type": "test", "event": "started", "name": "{}" }}"#,
320+
self.write_message(&*format!(r#"{{ "type": "test", "event": "started", "name": "{}" }}"#,
292321
desc.name))
293322
}
294323

@@ -348,19 +377,19 @@ impl<T: Write> OutputFormatter for JsonFormatter<T> {
348377
deviation,
349378
mbps);
350379

351-
self.write_str(&*line)
380+
self.write_message(&*line)
352381
},
353382
}
354383
}
355384

356385
fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> {
357-
self.write_str(&*format!(r#"{{ "type": "test", "event": "timeout", "name": "{}" }}"#,
386+
self.write_message(&*format!(r#"{{ "type": "test", "event": "timeout", "name": "{}" }}"#,
358387
desc.name))
359388
}
360389

361390
fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool> {
362391

363-
self.write_str(&*format!("{{ \"type\": \"suite\", \
392+
self.write_message(&*format!("{{ \"type\": \"suite\", \
364393
\"event\": \"{}\", \
365394
\"passed\": {}, \
366395
\"failed\": {}, \

src/libtest/lib.rs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -719,7 +719,7 @@ pub fn list_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Res
719719
};
720720

721721
let quiet = opts.format == OutputFormat::Terse;
722-
let mut out = HumanFormatter::new(output, use_color(opts), quiet, 0);
722+
let mut out = HumanFormatter::new(output, use_color(opts), quiet, 0, false);
723723
let mut st = ConsoleTestState::new(opts)?;
724724

725725
let mut ntest = 0;
@@ -820,23 +820,27 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Resu
820820
Some(t) => Pretty(t),
821821
};
822822

823-
let max_name_len = if let Some(t) = tests.iter().max_by_key(|t| len_if_padded(*t)) {
824-
let n = t.desc.name.as_slice();
825-
n.len()
826-
}
827-
else {
828-
0
823+
let max_name_len = tests.iter()
824+
.max_by_key(|t| len_if_padded(*t))
825+
.map(|t| t.desc.name.as_slice().len())
826+
.unwrap_or(0);
827+
828+
let is_multithreaded = match opts.test_threads {
829+
Some(n) => n > 1,
830+
None => get_concurrency() > 1,
829831
};
830832

831833
let mut out: Box<OutputFormatter> = match opts.format {
832834
OutputFormat::Pretty => Box::new(HumanFormatter::new(output,
833835
use_color(opts),
834836
false,
835-
max_name_len)),
837+
max_name_len,
838+
is_multithreaded)),
836839
OutputFormat::Terse => Box::new(HumanFormatter::new(output,
837840
use_color(opts),
838841
true,
839-
max_name_len)),
842+
max_name_len,
843+
is_multithreaded)),
840844
OutputFormat::Json => Box::new(JsonFormatter::new(output)),
841845
};
842846
let mut st = ConsoleTestState::new(opts)?;

0 commit comments

Comments
 (0)