TestComponent: implement word-diff

Signed-off-by: Maxime “pep” Buquet <pep@bouah.net>
This commit is contained in:
Maxime “pep” Buquet 2023-01-07 15:44:15 +01:00
parent d3e013a999
commit 6692443b18
Signed by: pep
GPG key ID: DEDA74AEECA9D0F2
2 changed files with 89 additions and 11 deletions

View file

@ -19,3 +19,4 @@ xmpp-parsers = { version = "^0.19", features = ["component"] }
[dev-dependencies]
syntect = "5.0"
diff = "0.1"

View file

@ -25,6 +25,7 @@ use std::task::Context;
use std::thread;
use async_trait::async_trait;
use diff;
use futures::{task::Poll, Stream};
use log::debug;
use syntect::{
@ -203,6 +204,92 @@ impl Component {
buf
}
fn hl_bg(color: String) -> String {
format!("{}{}", color, "\x1b[48;5;8m")
}
fn compare_hl(expected: &str, actual: &str) -> String {
let hl_expected = Component::hl(expected.clone());
let hl_actual = Component::hl(actual.clone());
if expected == actual {
return format!(
"\nexpected: `{}`\n \x1b[31mactual\x1b[0m: `{}`\n",
hl_expected, hl_actual
);
}
let mut buf_expected = String::new();
let mut buf_actual = String::new();
let mut last_color: Option<String> = None;
let mut color_start = false;
let mut color_added = false;
let mut clear_bg = false;
for diff in diff::chars(&hl_expected, &hl_actual) {
match diff {
diff::Result::Both(l, r) => {
if clear_bg {
buf_expected.push_str("\x1b[49m");
buf_actual.push_str("\x1b[49m");
clear_bg = false;
}
if l == '\x1b' {
last_color = Some(String::from(l));
color_start = true;
} else if color_start {
if l == 'm' {
color_start = false;
}
last_color = last_color.clone().map(|mut c| {
c.push(l);
c
});
}
buf_expected.push(l);
buf_actual.push(r);
}
ref result @ diff::Result::Left(ref c)
| ref result @ diff::Result::Right(ref c) => {
clear_bg = true;
if *c == '\x1b' {
last_color = Some(String::from(*c));
color_start = true;
color_added = false;
} else if color_start {
last_color = last_color.clone().map(|mut color| {
color.push(*c);
color
});
}
if ! color_added && ! color_start && let Some(ref color) = last_color {
buf_expected.push_str(format!("{}", Component::hl_bg(color.clone())).as_str());
color_added = true;
}
if color_start && *c == 'm' {
color_start = false;
}
match result {
diff::Result::Left(_) => buf_expected.push(*c),
diff::Result::Right(_) => buf_actual.push(*c),
_ => unreachable!(),
}
}
}
}
format!(
"\nexpected: `{}`\n \x1b[31mactual\x1b[0m: `{}`\n",
buf_expected, buf_actual
)
}
fn send_stanza_inner<E: Into<TestElement> + Send>(&mut self, el: E) -> Result<(), Error> {
let out: TestElement = el.into();
let dest: Jid = match out.attr("to") {
@ -218,19 +305,9 @@ impl Component {
Some(expected) => match expected {
Expect::Element(el) => {
let (expected, actual) = (String::from(&el), String::from(&out));
let hl_expected = Component::hl(expected.clone());
let hl_actual = Component::hl(actual.clone());
debug!("{}", Component::compare_hl(&expected, &actual));
if expected != actual {
debug!(
"\nexpected: `{}`\n \x1b[31mactual\x1b[0m: `{}`\n",
hl_expected, hl_actual
);
panic!("assertion failed: `(actual == expected)`")
} else {
debug!(
"\nexpected: `{}`\n \x1b[32mactual\x1b[0m: `{}`\n",
hl_expected, hl_actual
);
}
}
Expect::Iq(cb, _) => match Iq::try_from(out.0.clone()) {