Skip to content

Commit 7485daf

Browse files
committed
diff: add tests to cover heuristics
1 parent 79e0bcc commit 7485daf

File tree

1 file changed

+93
-0
lines changed

1 file changed

+93
-0
lines changed

tests/integration.rs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ mod common {
9595
}
9696

9797
mod diff {
98+
use std::process::Stdio;
99+
98100
use diffutilslib::assert_diff_eq;
99101

100102
use super::*;
@@ -341,6 +343,97 @@ mod diff {
341343

342344
Ok(())
343345
}
346+
347+
fn str_bar_diff(bar: &[u8]) -> String {
348+
String::from_utf8(
349+
bar.split(|b| *b == b'\n')
350+
.filter(|b| b != b"")
351+
.flat_map(|b| [b">", b" ", b, b"\n"].concat())
352+
.collect::<Vec<u8>>(),
353+
)
354+
.unwrap()
355+
}
356+
357+
#[test]
358+
fn large_similar_files() -> Result<(), Box<dyn std::error::Error>> {
359+
// Large similar files should still produce ideal diffs, not
360+
// triggering the total cost heuristic.
361+
let foo = b"f\n".repeat(16 * 1024 * 1024);
362+
let bar = b"b\n".repeat(26);
363+
364+
let mut file1 = NamedTempFile::new()?;
365+
file1.write_all(&foo)?;
366+
file1.write_all(&foo)?;
367+
let mut file2 = NamedTempFile::new()?;
368+
file2.write_all(&foo)?;
369+
file2.write_all(&bar)?;
370+
file2.write_all(&foo)?;
371+
372+
let mut cmd = Command::cargo_bin("diffutils")?;
373+
cmd.arg("diff").arg(file1.path()).arg(file2.path());
374+
cmd.assert()
375+
.code(predicate::eq(1))
376+
.failure()
377+
.stdout(predicate::eq(format!(
378+
"16777216a16777217,16777242\n{}",
379+
str_bar_diff(&bar)
380+
)));
381+
382+
let mut file1 = NamedTempFile::new()?;
383+
file1.write_all(&bar)?;
384+
file1.write_all(&foo)?;
385+
file1.write_all(&foo)?;
386+
let mut file2 = NamedTempFile::new()?;
387+
file2.write_all(&foo)?;
388+
file2.write_all(&foo)?;
389+
390+
let mut cmd = Command::cargo_bin("diffutils")?;
391+
cmd.arg("diff").arg(file1.path()).arg(file2.path());
392+
cmd.assert()
393+
.code(predicate::eq(1))
394+
.failure()
395+
.stdout(predicate::eq(format!(
396+
"1,26d0\n{}",
397+
str_bar_diff(&bar).replace(">", "<")
398+
)));
399+
400+
Ok(())
401+
}
402+
403+
#[test]
404+
fn large_different_files() -> Result<(), Box<dyn std::error::Error>> {
405+
let foo = b"f\n".repeat(4 * 1024 * 1024);
406+
let bar = b"b\n".repeat(26);
407+
let baz = b"z\n".repeat(4 * 1024 * 1024);
408+
409+
let mut file1 = NamedTempFile::new()?;
410+
file1.write_all(&foo)?;
411+
file1.write_all(&bar)?;
412+
let mut file2 = NamedTempFile::new()?;
413+
file2.write_all(&baz)?;
414+
file2.write_all(&bar)?;
415+
416+
let mut child = std::process::Command::new(assert_cmd::cargo::cargo_bin("diffutils"))
417+
.arg("diff")
418+
.arg(file1.path())
419+
.arg(file2.path())
420+
.stdout(Stdio::null())
421+
.spawn()
422+
.unwrap();
423+
424+
// The total cost heuristic should give up trying to find good split points
425+
// in a reasonable amount of time (can still be a fairly big in debug builds)
426+
for retries in 0.. {
427+
std::thread::sleep(std::time::Duration::from_secs(1));
428+
if let Some(status) = child.try_wait()? {
429+
assert_eq!(status.code(), Some(1));
430+
break;
431+
}
432+
assert!(retries < 10);
433+
}
434+
435+
Ok(())
436+
}
344437
}
345438

346439
mod cmp {

0 commit comments

Comments
 (0)