Skip to content

Commit

Permalink
Merge pull request #97 from tommilligan/96-regression
Browse files Browse the repository at this point in the history
fix: deleted trailing newline causes panic
  • Loading branch information
tommilligan committed Apr 2, 2022
2 parents 9654759 + 5407d10 commit ae6cc15
Showing 1 changed file with 123 additions and 6 deletions.
129 changes: 123 additions & 6 deletions pretty_assertions/src/printer.rs
Expand Up @@ -29,7 +29,7 @@ pub(crate) fn write_header(f: &mut fmt::Formatter) -> fmt::Result {
/// Delay formatting this deleted chunk until later.
///
/// It can be formatted as a whole chunk by calling `flush`, or the inner value
/// obtained with `take` for further processing.
/// obtained with `take` for further processing (such as an inline diff).
#[derive(Default)]
struct LatentDeletion<'a> {
// The most recent deleted line we've seen
Expand All @@ -47,7 +47,7 @@ impl<'a> LatentDeletion<'a> {

/// Take the underlying chunk value, if it's suitable for inline diffing.
///
/// If there is no value of we've seen more than one line, return `None`.
/// If there is no value or we've seen more than one line, return `None`.
fn take(&mut self) -> Option<&'a str> {
if self.count == 1 {
self.value.take()
Expand Down Expand Up @@ -100,10 +100,6 @@ pub(crate) fn write_lines<TWrite: fmt::Write>(
previous_deletion.flush(f)?;
previous_deletion.set(deleted);
}
// Underlying diff library should never return this sequence
(::diff::Result::Right(_), Some(::diff::Result::Left(_))) => {
panic!("insertion followed by deletion");
}
// If we're being followed by more insertions, don't inline diff
(::diff::Result::Right(inserted), Some(::diff::Result::Right(_))) => {
previous_deletion.flush(f)?;
Expand Down Expand Up @@ -478,4 +474,125 @@ Cabbage"#;

check_printer(write_lines, left, right, &expected);
}

mod write_lines_edge_newlines {
use super::*;

#[test]
fn both_trailing() {
let left = "fan\n";
let right = "mug\n";
// Note the additional space at the bottom is caused by a trailing newline
// adding an additional line with zero content to both sides of the diff
let expected = format!(
r#"{red_light}<{reset}{red_heavy}fan{reset}
{green_light}>{reset}{green_heavy}mug{reset}
"#,
red_light = RED_LIGHT,
red_heavy = RED_HEAVY,
green_light = GREEN_LIGHT,
green_heavy = GREEN_HEAVY,
reset = RESET,
);

check_printer(write_lines, left, right, &expected);
}

#[test]
fn both_leading() {
let left = "\nfan";
let right = "\nmug";
// Note the additional space at the top is caused by a leading newline
// adding an additional line with zero content to both sides of the diff
let expected = format!(
r#"
{red_light}<{reset}{red_heavy}fan{reset}
{green_light}>{reset}{green_heavy}mug{reset}
"#,
red_light = RED_LIGHT,
red_heavy = RED_HEAVY,
green_light = GREEN_LIGHT,
green_heavy = GREEN_HEAVY,
reset = RESET,
);

check_printer(write_lines, left, right, &expected);
}

#[test]
fn leading_added() {
let left = "fan";
let right = "\nmug";
let expected = format!(
r#"{red_light}<fan{reset}
{green_light}>{reset}
{green_light}>mug{reset}
"#,
red_light = RED_LIGHT,
green_light = GREEN_LIGHT,
reset = RESET,
);

check_printer(write_lines, left, right, &expected);
}

#[test]
fn leading_deleted() {
let left = "\nfan";
let right = "mug";
let expected = format!(
r#"{red_light}<{reset}
{red_light}<fan{reset}
{green_light}>mug{reset}
"#,
red_light = RED_LIGHT,
green_light = GREEN_LIGHT,
reset = RESET,
);

check_printer(write_lines, left, right, &expected);
}

#[test]
fn trailing_added() {
let left = "fan";
let right = "mug\n";
let expected = format!(
r#"{red_light}<fan{reset}
{green_light}>mug{reset}
{green_light}>{reset}
"#,
red_light = RED_LIGHT,
green_light = GREEN_LIGHT,
reset = RESET,
);

check_printer(write_lines, left, right, &expected);
}

/// Regression test for double abort
///
/// See: https://github.com/colin-kiegel/rust-pretty-assertions/issues/96
#[test]
fn trailing_deleted() {
// The below inputs caused an abort via double panic
// we panicked at 'insertion followed by deletion'
let left = "fan\n";
let right = "mug";
let expected = format!(
r#"{red_light}<{reset}{red_heavy}fan{reset}
{green_light}>{reset}{green_heavy}mug{reset}
{red_light}<{reset}
"#,
red_light = RED_LIGHT,
red_heavy = RED_HEAVY,
green_light = GREEN_LIGHT,
green_heavy = GREEN_HEAVY,
reset = RESET,
);

check_printer(write_lines, left, right, &expected);
}
}
}

0 comments on commit ae6cc15

Please sign in to comment.