Refactor diff handling in tests
This splits the generation and display of mismatches. Mismatches now include a few lines of context. Finally, diffs are now coloured.
This commit is contained in:
parent
b59ab9c13f
commit
adeafb3e45
29
Cargo.lock
generated
29
Cargo.lock
generated
@ -6,6 +6,7 @@ dependencies = [
|
||||
"regex 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"strings 0.0.1 (git+https://github.com/nrc/strings.rs.git)",
|
||||
"term 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"toml 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -22,6 +23,15 @@ name = "diff"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "kernel32-sys"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.1.8"
|
||||
@ -60,6 +70,15 @@ name = "strings"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/nrc/strings.rs.git#6d748148fbe3bf2d9e5ac2ede65ac503d7491a4f"
|
||||
|
||||
[[package]]
|
||||
name = "term"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.1.21"
|
||||
@ -68,3 +87,13 @@ dependencies = [
|
||||
"rustc-serialize 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-build"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
|
@ -19,3 +19,4 @@ rustc-serialize = "0.3.14"
|
||||
[dev-dependencies]
|
||||
diff = "0.1.0"
|
||||
regex = "0.1"
|
||||
term = "0.2"
|
||||
|
117
tests/system.rs
117
tests/system.rs
@ -13,14 +13,17 @@
|
||||
extern crate rustfmt;
|
||||
extern crate diff;
|
||||
extern crate regex;
|
||||
extern crate term;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{VecDeque, HashMap};
|
||||
use std::fs;
|
||||
use std::io::{self, Read, BufRead, BufReader};
|
||||
use std::thread;
|
||||
use rustfmt::*;
|
||||
use rustfmt::config::Config;
|
||||
|
||||
static DIFF_CONTEXT_SIZE: usize = 3;
|
||||
|
||||
fn get_path_string(dir_entry: io::Result<fs::DirEntry>) -> String {
|
||||
let path = dir_entry.ok().expect("Couldn't get DirEntry.").path();
|
||||
|
||||
@ -87,16 +90,40 @@ fn check_files<I>(files: I) -> (u32, u32)
|
||||
(count, fails)
|
||||
}
|
||||
|
||||
fn print_mismatches(result: HashMap<String, String>) {
|
||||
for (_, fmt_text) in result {
|
||||
println!("{}", fmt_text);
|
||||
fn print_mismatches(result: HashMap<String, Vec<Mismatch>>) {
|
||||
let mut t = term::stdout().unwrap();
|
||||
|
||||
for (file_name, diff) in result {
|
||||
for mismatch in diff {
|
||||
t.fg(term::color::BRIGHT_WHITE).unwrap();
|
||||
writeln!(t, "\nMismatch at {}:{}:", file_name, mismatch.line_number).unwrap();
|
||||
|
||||
for line in mismatch.lines {
|
||||
match line {
|
||||
DiffLine::Context(ref str) => {
|
||||
t.fg(term::color::WHITE).unwrap();
|
||||
writeln!(t, " {}⏎", str).unwrap();
|
||||
}
|
||||
DiffLine::Expected(ref str) => {
|
||||
t.fg(term::color::GREEN).unwrap();
|
||||
writeln!(t, "+{}⏎", str).unwrap();
|
||||
}
|
||||
DiffLine::Resulting(ref str) => {
|
||||
t.fg(term::color::RED).unwrap();
|
||||
writeln!(t, "-{}⏎", str).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert!(t.reset().unwrap());
|
||||
}
|
||||
|
||||
// Ick, just needed to get a &'static to handle_result.
|
||||
static HANDLE_RESULT: &'static Fn(HashMap<String, String>) = &handle_result;
|
||||
|
||||
pub fn idempotent_check(filename: String) -> Result<(), HashMap<String, String>> {
|
||||
pub fn idempotent_check(filename: String) -> Result<(), HashMap<String, Vec<Mismatch>>> {
|
||||
let sig_comments = read_significant_comments(&filename);
|
||||
let mut config = get_config(sig_comments.get("config").map(|x| &(*x)[..]));
|
||||
let args = vec!["rustfmt".to_owned(), filename];
|
||||
@ -179,10 +206,11 @@ fn handle_result(result: HashMap<String, String>) {
|
||||
// TODO: speedup by running through bytes iterator
|
||||
f.read_to_string(&mut text).ok().expect("Failed reading target.");
|
||||
if fmt_text != text {
|
||||
let diff_str = make_diff(&file_name, &fmt_text, &text);
|
||||
failures.insert(file_name, diff_str);
|
||||
let diff = make_diff(&fmt_text, &text, DIFF_CONTEXT_SIZE);
|
||||
failures.insert(file_name, diff);
|
||||
}
|
||||
}
|
||||
|
||||
if !failures.is_empty() {
|
||||
panic!(failures);
|
||||
}
|
||||
@ -199,36 +227,79 @@ fn get_target(file_name: &str, target: Option<&str>) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
// Produces a diff string between the expected output and actual output of
|
||||
// rustfmt on a given file
|
||||
fn make_diff(file_name: &str, expected: &str, actual: &str) -> String {
|
||||
pub enum DiffLine {
|
||||
Context(String),
|
||||
Expected(String),
|
||||
Resulting(String),
|
||||
}
|
||||
|
||||
pub struct Mismatch {
|
||||
line_number: u32,
|
||||
pub lines: Vec<DiffLine>,
|
||||
}
|
||||
|
||||
impl Mismatch {
|
||||
fn new(line_number: u32) -> Mismatch {
|
||||
Mismatch { line_number: line_number, lines: Vec::new() }
|
||||
}
|
||||
}
|
||||
|
||||
// Produces a diff between the expected output and actual output of rustfmt.
|
||||
fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec<Mismatch> {
|
||||
let mut line_number = 1;
|
||||
let mut prev_both = true;
|
||||
let mut text = String::new();
|
||||
let mut context_queue: VecDeque<&str> = VecDeque::with_capacity(context_size);
|
||||
let mut lines_since_mismatch = context_size + 1;
|
||||
let mut results = Vec::new();
|
||||
let mut mismatch = Mismatch::new(0);
|
||||
|
||||
for result in diff::lines(expected, actual) {
|
||||
match result {
|
||||
diff::Result::Left(str) => {
|
||||
if prev_both {
|
||||
text.push_str(&format!("Mismatch @ {}:{}\n", file_name, line_number));
|
||||
if lines_since_mismatch >= context_size {
|
||||
results.push(mismatch);
|
||||
mismatch = Mismatch::new(line_number - context_queue.len() as u32);
|
||||
}
|
||||
text.push_str(&format!("-{}⏎\n", str));
|
||||
prev_both = false;
|
||||
|
||||
while let Some(line) = context_queue.pop_front() {
|
||||
mismatch.lines.push(DiffLine::Context(line.to_owned()));
|
||||
}
|
||||
|
||||
mismatch.lines.push(DiffLine::Resulting(str.to_owned()));
|
||||
lines_since_mismatch = 0;
|
||||
}
|
||||
diff::Result::Right(str) => {
|
||||
if prev_both {
|
||||
text.push_str(&format!("Mismatch @ {}:{}\n", file_name, line_number));
|
||||
if lines_since_mismatch >= context_size {
|
||||
results.push(mismatch);
|
||||
mismatch = Mismatch::new(line_number - context_queue.len() as u32);
|
||||
}
|
||||
text.push_str(&format!("+{}⏎\n", str));
|
||||
prev_both = false;
|
||||
|
||||
while let Some(line) = context_queue.pop_front() {
|
||||
mismatch.lines.push(DiffLine::Context(line.to_owned()));
|
||||
}
|
||||
|
||||
mismatch.lines.push(DiffLine::Expected(str.to_owned()));
|
||||
line_number += 1;
|
||||
lines_since_mismatch = 0;
|
||||
}
|
||||
diff::Result::Both(..) => {
|
||||
diff::Result::Both(str, _) => {
|
||||
if context_queue.len() >= context_size {
|
||||
let _ = context_queue.pop_front();
|
||||
}
|
||||
|
||||
if lines_since_mismatch < context_size {
|
||||
mismatch.lines.push(DiffLine::Context(str.to_owned()));
|
||||
} else {
|
||||
context_queue.push_back(str);
|
||||
}
|
||||
|
||||
line_number += 1;
|
||||
prev_both = true;
|
||||
lines_since_mismatch += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
text
|
||||
results.push(mismatch);
|
||||
results.remove(0);
|
||||
|
||||
results
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user