Skip to content

Commit 219360c

Browse files
committed
[nextest-runner] handle outputs with/without trailing newlines better
Previously, our headers would always insert a leading newline to compensate for situations where the output didn't have a trailing newline in it. This isn't quite right (what if the last output doesn't have a newline in it)? It also causes issues with situations where RESET_COLOR needs to be inserted immediately before the last newline. Change our code to always insert a trailing newline, and the trailer immediately before that.
1 parent a3eedfb commit 219360c

File tree

1 file changed

+33
-15
lines changed

1 file changed

+33
-15
lines changed

nextest-runner/src/reporter/displayer.rs

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,7 +1365,7 @@ impl<'a> TestReporterImpl<'a> {
13651365

13661366
let stdout_header = {
13671367
format!(
1368-
"\n{} {:19} {}",
1368+
"{} {:19} {}",
13691369
"---- ".style(header_style),
13701370
"STDOUT:".style(header_style),
13711371
self.display_script_instance(script_id.clone(), command, args),
@@ -1374,7 +1374,7 @@ impl<'a> TestReporterImpl<'a> {
13741374

13751375
let stderr_header = {
13761376
format!(
1377-
"\n{} {:19} {}",
1377+
"{} {:19} {}",
13781378
"---- ".style(header_style),
13791379
"STDERR:".style(header_style),
13801380
self.display_script_instance(script_id.clone(), command, args),
@@ -1435,7 +1435,7 @@ impl<'a> TestReporterImpl<'a> {
14351435

14361436
let stdout_header = {
14371437
let mut header = String::new();
1438-
swrite!(header, "\n{}", "---- ".style(header_style));
1438+
swrite!(header, "{}", "---- ".style(header_style));
14391439
let out_len = self.write_attempt(run_status, header_style, &mut header);
14401440
// The width is to align test instances.
14411441
swrite!(
@@ -1450,7 +1450,7 @@ impl<'a> TestReporterImpl<'a> {
14501450

14511451
let stderr_header = {
14521452
let mut header = String::new();
1453-
swrite!(header, "\n{}", "---- ".style(header_style));
1453+
swrite!(header, "{}", "---- ".style(header_style));
14541454
let out_len = self.write_attempt(run_status, header_style, &mut header);
14551455
// The width is to align test instances.
14561456
swrite!(
@@ -1465,7 +1465,7 @@ impl<'a> TestReporterImpl<'a> {
14651465

14661466
let combined_header = {
14671467
let mut header = String::new();
1468-
swrite!(header, "\n{}", "---- ".style(header_style));
1468+
swrite!(header, "{}", "---- ".style(header_style));
14691469
let out_len = self.write_attempt(run_status, header_style, &mut header);
14701470
// The width is to align test instances.
14711471
swrite!(
@@ -1585,13 +1585,12 @@ impl<'a> TestReporterImpl<'a> {
15851585
} else {
15861586
// Output the text without stripping ANSI escapes, then reset the color afterwards
15871587
// in case the output is malformed.
1588-
writer.write_all(&output.buf)?;
1589-
writer.write_all(RESET_COLOR)?;
1588+
write_output_with_trailing_newline(&output.buf, RESET_COLOR, writer)?;
15901589
}
15911590
} else {
15921591
// Strip ANSI escapes from the output if nextest itself isn't colorized.
15931592
let mut no_color = strip_ansi_escapes::Writer::new(writer);
1594-
no_color.write_all(&output.buf)?;
1593+
write_output_with_trailing_newline(&output.buf, b"", &mut no_color)?;
15951594
}
15961595

15971596
Ok(())
@@ -1665,12 +1664,31 @@ fn write_output_with_highlight(
16651664
// `end` is guaranteed to be within the bounds of `output.buf`. (It is actually safe
16661665
// for it to be equal to `output.buf.len()` -- it gets treated as an empty list in
16671666
// that case.)
1668-
writer.write_all(&output[end..])?;
1669-
writer.write_all(RESET_COLOR)?;
1667+
write_output_with_trailing_newline(&output[end..], RESET_COLOR, writer)?;
16701668

16711669
Ok(())
16721670
}
16731671

1672+
/// Write output, always ensuring there's a trailing newline. (If there's no
1673+
/// newline, one will be inserted.)
1674+
///
1675+
/// `trailer` is written immediately before the trailing newline if any.
1676+
fn write_output_with_trailing_newline(
1677+
mut output: &[u8],
1678+
trailer: &[u8],
1679+
writer: &mut dyn Write,
1680+
) -> io::Result<()> {
1681+
// If there's a trailing newline in the output, insert the trailer right
1682+
// before it.
1683+
if output.last() == Some(&b'\n') {
1684+
output = &output[..output.len() - 1];
1685+
}
1686+
1687+
writer.write_all(output)?;
1688+
writer.write_all(trailer)?;
1689+
writer.write_all(b"\n")
1690+
}
1691+
16741692
struct FmtPrefix<'a>(&'a Style);
16751693

16761694
impl fmt::Display for FmtPrefix<'_> {
@@ -2411,20 +2429,20 @@ mod tests {
24112429

24122430
assert_eq!(
24132431
write_output_with_highlight_buf("output", 0, Some(6)),
2414-
format!("{RESET_COLOR}{BOLD_RED}output{RESET_COLOR}{RESET_COLOR}")
2432+
format!("{RESET_COLOR}{BOLD_RED}output{RESET_COLOR}{RESET_COLOR}\n")
24152433
);
24162434

24172435
assert_eq!(
24182436
write_output_with_highlight_buf("output", 1, Some(5)),
2419-
format!("o{RESET_COLOR}{BOLD_RED}utpu{RESET_COLOR}t{RESET_COLOR}")
2437+
format!("o{RESET_COLOR}{BOLD_RED}utpu{RESET_COLOR}t{RESET_COLOR}\n")
24202438
);
24212439

24222440
assert_eq!(
2423-
write_output_with_highlight_buf("output\nhighlight 1\nhighlight 2", 7, None),
2441+
write_output_with_highlight_buf("output\nhighlight 1\nhighlight 2\n", 7, None),
24242442
format!(
24252443
"output\n{RESET_COLOR}\
24262444
{BOLD_RED}highlight 1{RESET_COLOR}\n\
2427-
{BOLD_RED}highlight 2{RESET_COLOR}{RESET_COLOR}"
2445+
{BOLD_RED}highlight 2{RESET_COLOR}{RESET_COLOR}\n"
24282446
)
24292447
);
24302448

@@ -2438,7 +2456,7 @@ mod tests {
24382456
"output\n{RESET_COLOR}\
24392457
{BOLD_RED}highlight 1{RESET_COLOR}\n\
24402458
{BOLD_RED}highlight 2{RESET_COLOR}\n\
2441-
not highlighted{RESET_COLOR}"
2459+
not highlighted{RESET_COLOR}\n"
24422460
)
24432461
);
24442462
}

0 commit comments

Comments
 (0)