use crate::{MMBlocks, MMFile};
#[test]
fn new_empty() {
let mut f = MMFile::new();
assert_eq!(f.size(), 0);
assert!(f.is_compact());
}
#[test]
fn new_from_bytes() {
let data = b"hello world";
let mut f = MMFile::from_bytes(data);
assert_eq!(f.size(), data.len());
assert!(f.is_compact());
}
#[test]
fn large_from_bytes() {
let mut data = Vec::new();
data.extend((0..240).cycle().take(15_000));
let mut f = MMFile::from_bytes(data.as_slice());
assert_eq!(f.size(), data.len());
assert!(f.is_compact());
}
#[test]
fn clone() {
let mut data = Vec::new();
data.extend((0..240).cycle().take(15_000));
let f = MMFile::from_bytes(data.as_slice());
let f2 = f.clone();
assert!(f == f2);
}
#[test]
fn clone_blocks() {
let mut data = Vec::new();
data.extend((0..240).cycle().take(15_000));
let mut f = MMBlocks::from_bytes(data.as_slice());
let mut f2 = f.clone();
assert!(f.eq(&mut f2));
}
#[test]
fn eq() {
let mut data = Vec::new();
data.extend((0..240).cycle().take(15_000));
let f = MMFile::from_bytes(data.as_slice());
let mut f2 = MMFile::from_bytes(data.as_slice());
assert!(f.eq(&mut f2));
}
#[test]
fn as_slice() {
assert_eq!(MMFile::new().as_slice(), &[]);
let mut data = Vec::new();
data.extend((0..240).cycle().take(15_000));
let f = MMFile::from_bytes(data.as_slice());
assert_eq!(f.as_slice(), &data);
}
#[test]
fn as_slice_mut() {
assert_eq!(MMFile::new().as_slice_mut(), &mut []);
let mut data = Vec::new();
data.extend((0..240).cycle().take(15_000));
let mut f = MMFile::from_bytes(data.as_slice());
assert_eq!(f.as_slice()[0], data[0]);
f.as_slice_mut()[0] += 1;
assert_eq!(f.as_slice()[0], data[0] + 1);
}
#[test]
fn diff_simple() {
let data = b"hello world\n";
let mut f = MMFile::from_bytes(data);
let data2 = b"hello world!\n";
let mut f2 = MMFile::from_bytes(data2);
let mut lines = Vec::<Vec<u8>>::new();
f.diff_raw(&mut f2, |line: &[u8]| {
lines.push(line.to_owned());
})
.unwrap();
let str_lines: Vec<String> = lines
.iter()
.map(|l| String::from_utf8_lossy(l).into_owned())
.collect();
assert_eq!(
str_lines,
vec![
"@@ -1,1 +1,1 @@\n",
"-",
"hello world\n",
"+",
"hello world!\n",
],
)
}
#[test]
fn diff_panic() {
let data = b"hello world\n";
let mut f = MMFile::from_bytes(data);
let data2 = b"hello world!\n";
let mut f2 = MMFile::from_bytes(data2);
let mut lines = Vec::<Vec<u8>>::new();
let diff_result = f.diff_raw(&mut f2, |line: &[u8]| {
if lines.len() > 1 {
panic!("too many lines!");
}
lines.push(line.to_owned());
});
assert_eq!(
diff_result,
Result::Err("diff failed with err: -1".to_owned())
);
}
#[test]
fn diff_with_mutation() {
let data = b"hello world\n";
let mut f = MMFile::from_bytes(data);
let data2 = b"hello world!\n";
let mut f2 = MMFile::from_bytes(data2);
let mut lines = Vec::<Vec<u8>>::new();
f.diff_raw(&mut f2, |line: &[u8]| {
lines.push(line.to_owned());
})
.unwrap();
let str_lines: Vec<String> = lines
.iter()
.map(|l| String::from_utf8_lossy(l).into_owned())
.collect();
assert_eq!(
str_lines,
vec![
"@@ -1,1 +1,1 @@\n",
"-",
"hello world\n",
"+",
"hello world!\n",
],
);
f2.as_slice_mut()[0] = "j".as_bytes()[0];
let mut lines = Vec::<Vec<u8>>::new();
f.diff_raw(&mut f2, |line: &[u8]| {
lines.push(line.to_owned());
})
.unwrap();
let str_lines: Vec<String> = lines
.iter()
.map(|l| String::from_utf8_lossy(l).into_owned())
.collect();
assert_eq!(
str_lines,
vec![
"@@ -1,1 +1,1 @@\n",
"-",
"hello world\n",
"+",
"jello world!\n", ],
);
}
#[test]
fn merge3_simple() {
let data = b"header\nline2\nline3\nline4\nhello world\n";
let mut f = MMFile::from_bytes(data);
let data2 = b"header\nline2\nline3\nline4\nhello world changed\n";
let mut f2 = MMFile::from_bytes(data2);
let data3 = b"header_changed\nline2\nline3\nline4\nhello world\n";
let mut f3 = MMFile::from_bytes(data3);
let mut lines = Vec::<Vec<u8>>::new();
let mut lines_rejected = Vec::<Vec<u8>>::new();
MMFile::merge3_raw(
&mut f,
&mut f2,
&mut f3,
|line: &[u8]| {
lines.push(line.to_owned());
},
|rej_line: &[u8]| {
lines_rejected.push(rej_line.to_owned());
},
)
.unwrap();
let str_lines: Vec<String> = lines
.iter()
.map(|l| String::from_utf8_lossy(l).into_owned())
.collect();
let str_rejected_lines: Vec<String> = lines_rejected
.iter()
.map(|l| String::from_utf8_lossy(l).into_owned())
.collect();
eprintln!("{:?}", str_lines);
eprintln!("{:?}", str_rejected_lines);
assert_eq!(
str_lines,
vec![
"header_changed\n",
"line2\n",
"line3\n",
"line4\n",
"hello world changed\n"
],
);
assert_eq!(str_rejected_lines, Vec::<String>::new());
}
#[test]
fn merge3_conflicts() {
let data = b"header\nline2\nline3\nline4\nhello world\n";
let mut f = MMFile::from_bytes(data);
let data2 = b"header\nline2\nline3\nline4\nhello world changed\n";
let mut f2 = MMFile::from_bytes(data2);
let data3 = b"header\nline2\nline3\nline4\nhello world also changed\n";
let mut f3 = MMFile::from_bytes(data3);
let mut lines = Vec::<Vec<u8>>::new();
let mut lines_rejected = Vec::<Vec<u8>>::new();
MMFile::merge3_raw(
&mut f,
&mut f2,
&mut f3,
|line: &[u8]| {
lines.push(line.to_owned());
},
|rej_line: &[u8]| {
lines_rejected.push(rej_line.to_owned());
},
)
.unwrap();
let str_lines: Vec<String> = lines
.iter()
.map(|l| String::from_utf8_lossy(l).into_owned())
.collect();
let str_rejected_lines: Vec<String> = lines_rejected
.iter()
.map(|l| String::from_utf8_lossy(l).into_owned())
.collect();
eprintln!("{:?}", str_lines);
eprintln!("{:?}", str_rejected_lines);
assert_eq!(
str_lines,
vec![
"header\n",
"line2\n",
"line3\n",
"line4\n",
"hello world changed\n"
],
);
assert_eq!(
str_rejected_lines,
vec![
"@@ -2,4 +2,4 @@\n",
" line2\n",
" line3\n",
" line4\n",
"-hello world\n",
"+hello world also changed\n",
],
);
}
#[test]
fn merge3_panic_emit() {
let data = b"header\nline2\nline3\nline4\nhello world\n";
let mut f = MMFile::from_bytes(data);
let data2 = b"header\nline2\nline3\nline4\nhello world changed\n";
let mut f2 = MMFile::from_bytes(data2);
let data3 = b"header_changed\nline2\nline3\nline4\nhello world\n";
let mut f3 = MMFile::from_bytes(data3);
let mut lines = Vec::<Vec<u8>>::new();
let mut lines_rejected = Vec::<Vec<u8>>::new();
let merge_result = MMFile::merge3_raw(
&mut f,
&mut f2,
&mut f3,
|line: &[u8]| {
if lines.len() > 2 {
panic!("too many lines!");
}
lines.push(line.to_owned());
},
|rej_line: &[u8]| {
lines_rejected.push(rej_line.to_owned());
},
);
assert_eq!(
merge_result,
Result::Err("merge failed with err: -1".to_owned())
);
}
#[test]
fn merge3_panic_reject() {
let data = b"header\nline2\nline3\nline4\nhello world\n";
let mut f = MMFile::from_bytes(data);
let data2 = b"header\nline2\nline3\nline4\nhello world changed\n";
let mut f2 = MMFile::from_bytes(data2);
let data3 = b"header\nline2\nline3\nline4\nhello world changed\n";
let mut f3 = MMFile::from_bytes(data3);
let mut lines = Vec::<Vec<u8>>::new();
let mut lines_rejected = Vec::<Vec<u8>>::new();
let merge_result = MMFile::merge3_raw(
&mut f,
&mut f2,
&mut f3,
|line: &[u8]| {
lines.push(line.to_owned());
},
|rej_line: &[u8]| {
if lines_rejected.len() > 2 {
panic!("too many lines!");
}
lines_rejected.push(rej_line.to_owned());
},
);
assert_eq!(
merge_result,
Result::Err("merge failed with err: -1".to_owned())
);
}
#[test]
fn patch_simple() {
let data = b"header\nline2\nline3\nline4\nhello world\n";
let mut f = MMFile::from_bytes(data);
let data2 = b"header\nline2\nline3\nline4\nhello world changed\n";
let mut f2 = MMFile::from_bytes(data2);
let data3 = b"header\nline2\nline3\nline4\nhello world changed\n";
let mut f3 = MMFile::from_bytes(data3);
let mut patch = f.compute_patch(&mut f2).unwrap();
let patch_result = f.apply_patch(&mut patch).unwrap();
assert!(patch_result.eq(&mut f3));
}
#[test]
fn patch_reject() {
let data = b"header\nline2\nline3\nline4\nhello world\n";
let mut f = MMFile::from_bytes(data);
let data2 = b"header changed\nline2\nline3\nline4\nhello world changed\n";
let mut f2 = MMFile::from_bytes(data2);
let mut patch = f.compute_patch(&mut f2).unwrap();
eprintln!("patch: {:?}", patch.clone().to_mmfile());
f.as_slice_mut()[0] = "b".as_bytes()[0];
let patch_result = f.apply_patch(&mut patch);
assert_eq!(patch_result, Err((f.clone(), patch.clone().to_mmfile())));
}