Skip to content

Commit cc5b9d7

Browse files
committed
use ariadne for test outputs
1 parent 82cda17 commit cc5b9d7

File tree

2 files changed

+89
-29
lines changed

2 files changed

+89
-29
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ repository = "https://github.com/FyraLabs/yttml"
1212
[dev-dependencies]
1313
chumsky = "0.11.1"
1414
ass-core = { workspace = true }
15+
ariadne = "0.5.1"
1516

1617
[dependencies]
1718
aspasia = "0.2.1"
@@ -23,7 +24,6 @@ serde_json = "1.0.127"
2324
serde_yml = "0.0.12"
2425
srv3-ttml = { path = "crates/srv3-ttml", version = "0.1.0" }
2526
srv3tovtt-crate = { path = "crates/srv3tovtt-crate" }
26-
similar = "2.5"
2727

2828
[workspace]
2929
members = ["crates/srv3-ttml", "crates/srv3tovtt-crate"]

src/tests/ass_test_helpers.rs

Lines changed: 88 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1+
use ariadne::{sources, Color, Label, Report, ReportKind};
12
use ass_core::parser::{ast::Event, Script};
23
use chumsky::prelude::*;
3-
use similar::TextDiff;
44

55
/// Parse an ASS file using the ass-core parser
66
pub fn parse_ass(content: &str) -> Result<Script<'_>, String> {
@@ -194,21 +194,92 @@ fn escape_debug_str(input: &str) -> String {
194194
format!("{}", input.escape_debug())
195195
}
196196

197+
fn diff_spans(expected: &str, actual: &str) -> ((usize, usize), (usize, usize)) {
198+
if expected == actual {
199+
let len = expected.len();
200+
return ((len, len), (len, len));
201+
}
202+
203+
let mut prefix_bytes = 0;
204+
for (exp_char, act_char) in expected.chars().zip(actual.chars()) {
205+
if exp_char == act_char {
206+
prefix_bytes += exp_char.len_utf8();
207+
} else {
208+
break;
209+
}
210+
}
211+
212+
let expected_tail = &expected[prefix_bytes..];
213+
let actual_tail = &actual[prefix_bytes..];
214+
215+
let mut suffix_bytes = 0;
216+
let mut expected_tail_iter = expected_tail.chars().rev();
217+
let mut actual_tail_iter = actual_tail.chars().rev();
218+
loop {
219+
match (expected_tail_iter.next(), actual_tail_iter.next()) {
220+
(Some(exp_char), Some(act_char)) if exp_char == act_char => {
221+
suffix_bytes += exp_char.len_utf8();
222+
223+
if prefix_bytes + suffix_bytes >= expected.len()
224+
|| prefix_bytes + suffix_bytes >= actual.len()
225+
{
226+
break;
227+
}
228+
}
229+
_ => break,
230+
}
231+
}
232+
233+
let mut expected_end = expected.len().saturating_sub(suffix_bytes);
234+
let mut actual_end = actual.len().saturating_sub(suffix_bytes);
235+
236+
if expected_end < prefix_bytes {
237+
expected_end = prefix_bytes;
238+
}
239+
if actual_end < prefix_bytes {
240+
actual_end = prefix_bytes;
241+
}
242+
243+
((prefix_bytes, expected_end), (prefix_bytes, actual_end))
244+
}
245+
197246
fn format_diff_output(expected: &str, actual: &str) -> String {
198-
let expected_display = format!("{}\n", escape_debug_str(expected));
199-
let actual_display = format!("{}\n", escape_debug_str(actual));
247+
let expected_display = escape_debug_str(expected);
248+
let actual_display = escape_debug_str(actual);
249+
250+
let ((expected_start, expected_end), (actual_start, actual_end)) =
251+
diff_spans(&expected_display, &actual_display);
252+
253+
let report = Report::build(
254+
ReportKind::Error,
255+
("actual.ass", actual_start..actual_start),
256+
)
257+
.with_message("ASS text mismatch")
258+
.with_label(
259+
Label::new(("expected.ass", expected_start..expected_end))
260+
.with_message("expected segment")
261+
.with_color(Color::Yellow),
262+
)
263+
.with_label(
264+
Label::new(("actual.ass", actual_start..actual_end))
265+
.with_message("actual segment")
266+
.with_color(Color::Cyan),
267+
)
268+
.finish();
200269

201-
let diff = TextDiff::from_lines(&expected_display, &actual_display);
202270
let mut buffer = Vec::new();
203-
diff.unified_diff()
204-
.context_radius(0)
205-
.header("expected", "actual")
206-
.to_writer(&mut buffer)
207-
.expect("writing diff to buffer");
208-
209-
let diff_string =
210-
String::from_utf8(buffer).unwrap_or_else(|_| "<diff output not valid UTF-8>".to_string());
211-
diff_string
271+
if let Err(err) = report.write(
272+
sources([
273+
("expected.ass", expected_display.as_str()),
274+
("actual.ass", actual_display.as_str()),
275+
]),
276+
&mut buffer,
277+
) {
278+
return format!(" <failed to render ariadne report: {}>", err);
279+
}
280+
281+
String::from_utf8(buffer)
282+
.unwrap_or_else(|_| "<ariadne output not valid UTF-8>".to_string())
212283
.lines()
213284
.map(|line| format!(" {}", line))
214285
.collect::<Vec<_>>()
@@ -369,32 +440,21 @@ pub fn compare_ass_files(expected: &Script<'_>, actual: &Script<'_>) -> Result<(
369440
FuzzyMatchResult::NumericOnly => {
370441
let diff_view = format_diff_output(exp_event.text, act_event.text);
371442
warnings.push(format!(
372-
"Event {}: text numeric-only mismatch downgraded to warning:\n expected: \"{}\"\n actual: \"{}\"\n{}",
373-
i,
374-
escape_debug_str(exp_event.text),
375-
escape_debug_str(act_event.text),
376-
diff_view
443+
"Event {}: text numeric-only mismatch downgraded to warning:\n{}",
444+
i, diff_view
377445
));
378446
}
379447
FuzzyMatchResult::Different => {
380448
if pos_difference_only(exp_event.text, act_event.text) {
381449
let diff_view = format_diff_output(exp_event.text, act_event.text);
382450
warnings.push(format!(
383-
"Event {}: text mismatch limited to pos() rounding, downgraded to warning:\n expected: \"{}\"\n actual: \"{}\"\n{}",
451+
"Event {}: text mismatch limited to pos() rounding, downgraded to warning:\n{}",
384452
i,
385-
escape_debug_str(exp_event.text),
386-
escape_debug_str(act_event.text),
387453
diff_view
388454
));
389455
} else {
390456
let diff_view = format_diff_output(exp_event.text, act_event.text);
391-
errors.push(format!(
392-
"Event {}: text mismatch:\n expected: \"{}\"\n actual: \"{}\"\n{}",
393-
i,
394-
escape_debug_str(exp_event.text),
395-
escape_debug_str(act_event.text),
396-
diff_view
397-
));
457+
errors.push(format!("Event {}: text mismatch:\n{}", i, diff_view));
398458
}
399459
}
400460
}

0 commit comments

Comments
 (0)