use super::*;
use crate::encoding::ldm::table::LdmHashTable;
fn fresh_table() -> LdmHashTable {
LdmHashTable::new(4, 2)
}
#[test]
fn count_backwards_match_walks_until_mismatch_or_bound() {
let history = b"abc__abc";
let len = count_backwards_match(history, 8, 0, 3, 0);
assert_eq!(len, 3);
let len2 = count_backwards_match(history, 5, 0, 0, 0);
assert_eq!(len2, 0);
}
#[test]
fn count_backwards_match_respects_anchor_bound() {
let history = b"aaaaaaaa";
let len = count_backwards_match(history, 6, 5, 4, 0);
assert_eq!(len, 1);
}
#[test]
fn find_best_match_returns_none_on_checksum_mismatch() {
let mut table = fresh_table();
table.insert_absolute(1, 4, 0x1111_1111);
let history = b"abcdefghabcdefgh";
let m = find_best_match(
&table,
1,
0xDEAD_BEEF,
FindBestMatchInputs {
live_history: history,
history_abs_start: 0,
split_abs: 8,
anchor_abs: 0,
lowest_index_abs: 0,
iend_abs: history.len(),
min_match_length: 4,
},
);
assert!(m.is_none(), "wrong checksum must be filtered out");
}
#[test]
fn find_best_match_rejects_stale_entries() {
let mut table = fresh_table();
table.insert_absolute(1, 4, 0xCAFE);
let history = b"abcdefghabcdefgh";
let m = find_best_match(
&table,
1,
0xCAFE,
FindBestMatchInputs {
live_history: history,
history_abs_start: 0,
split_abs: 8,
anchor_abs: 0,
lowest_index_abs: 5,
iend_abs: history.len(),
min_match_length: 4,
},
);
assert!(m.is_none(), "stale entry must be filtered out");
}
#[test]
fn find_best_match_picks_longest_combined_match() {
let mut table = fresh_table();
table.insert_absolute(1, 4, 0xCAFE);
let history = b"PPPPabcdefghabcdefgh";
let m = find_best_match(
&table,
1,
0xCAFE,
FindBestMatchInputs {
live_history: history,
history_abs_start: 0,
split_abs: 12,
anchor_abs: 12,
lowest_index_abs: 0,
iend_abs: history.len(),
min_match_length: 4,
},
)
.expect("a valid candidate must be found");
assert_eq!(m.match_pos, 4);
assert_eq!(m.forward_len, 8);
assert_eq!(m.backward_len, 0);
assert_eq!(m.total_len(), 8);
}
#[test]
fn find_best_match_extends_backwards_into_pre_split_bytes() {
let mut table = fresh_table();
table.insert_absolute(1, 2, 0xCAFE);
let history = b"XYabcdefghXYabcdefgh";
let m = find_best_match(
&table,
1,
0xCAFE,
FindBestMatchInputs {
live_history: history,
history_abs_start: 0,
split_abs: 12,
anchor_abs: 10,
lowest_index_abs: 0,
iend_abs: history.len(),
min_match_length: 4,
},
)
.expect("a valid candidate must be found");
assert_eq!(m.match_pos, 2);
assert_eq!(m.forward_len, 8);
assert_eq!(m.backward_len, 2);
assert_eq!(m.total_len(), 10);
}
#[test]
fn find_best_match_prefers_longer_total_across_slots() {
let mut table = fresh_table();
table.insert_absolute(1, 4, 0xCAFE);
table.insert_absolute(1, 8, 0xCAFE);
let history = b"PPPPabcdabcdefghabcdefgh";
let m = find_best_match(
&table,
1,
0xCAFE,
FindBestMatchInputs {
live_history: history,
history_abs_start: 0,
split_abs: 16,
anchor_abs: 16,
lowest_index_abs: 0,
iend_abs: history.len(),
min_match_length: 4,
},
)
.expect("a valid candidate must be found");
assert_eq!(m.match_pos, 8, "longer-forward winner must be picked");
assert_eq!(m.forward_len, 8);
}
#[test]
fn find_best_match_rejects_entries_at_or_past_split() {
let mut table = fresh_table();
table.insert_absolute(1, 12, 0xCAFE);
let history = b"PPPPabcdefghabcdefgh";
let m = find_best_match(
&table,
1,
0xCAFE,
FindBestMatchInputs {
live_history: history,
history_abs_start: 0,
split_abs: 12,
anchor_abs: 12,
lowest_index_abs: 0,
iend_abs: history.len(),
min_match_length: 4,
},
);
assert!(m.is_none(), "entry at split_abs must be rejected");
let mut table_after = fresh_table();
table_after.insert_absolute(1, 16, 0xCAFE);
let m_after = find_best_match(
&table_after,
1,
0xCAFE,
FindBestMatchInputs {
live_history: history,
history_abs_start: 0,
split_abs: 12,
anchor_abs: 12,
lowest_index_abs: 0,
iend_abs: history.len(),
min_match_length: 4,
},
);
assert!(m_after.is_none(), "entry past split_abs must be rejected");
}
#[test]
fn find_best_match_forward_count_is_bounded_by_iend_abs() {
let mut table = fresh_table();
table.insert_absolute(1, 4, 0xCAFE);
let history = b"PPPPabcdefghabcdefgh";
let m = find_best_match(
&table,
1,
0xCAFE,
FindBestMatchInputs {
live_history: history,
history_abs_start: 0,
split_abs: 12,
anchor_abs: 12,
lowest_index_abs: 0,
iend_abs: 16, min_match_length: 4,
},
)
.expect("a 4-byte forward match still passes the min_match floor");
assert_eq!(
m.forward_len, 4,
"forward count must cap at iend_abs - split_abs"
);
}
#[test]
fn find_best_match_filters_short_forward_matches() {
let mut table = fresh_table();
table.insert_absolute(1, 4, 0xCAFE);
let history = b"PPPPabXXXXXXab";
let m = find_best_match(
&table,
1,
0xCAFE,
FindBestMatchInputs {
live_history: history,
history_abs_start: 0,
split_abs: 12,
anchor_abs: 12,
lowest_index_abs: 0,
iend_abs: history.len(),
min_match_length: 4,
},
);
assert!(m.is_none());
}