use super::*;
#[test]
fn new_uses_level_1_defaults() {
let m = FastKernelMatcher::new();
assert_eq!(m.window_log, FAST_LEVEL_1_WINDOW_LOG);
assert_eq!(m.hash_table.hash_log(), FAST_LEVEL_1_HASH_LOG);
assert_eq!(m.hash_table.mls(), FAST_LEVEL_1_MLS);
assert_eq!(m.rep, FAST_INITIAL_REP);
assert_eq!(m.offset_hist, FAST_INITIAL_OFFSET_HIST);
assert_eq!(m.max_window_size, 1usize << FAST_LEVEL_1_WINDOW_LOG);
assert_eq!(m.history.len(), HISTORY_DRAIN_BASE);
assert_eq!(m.prefix_start_index, INITIAL_PREFIX_START_INDEX);
assert!(m.pending.is_none());
}
#[test]
fn borrowed_window_reads_match_owned_then_restores() {
let mut m = FastKernelMatcher::new();
m.history = b"owned-history-bytes".to_vec();
assert_eq!(m.history_bytes(), b"owned-history-bytes");
let external = b"a-different-borrowed-window".to_vec();
unsafe { m.set_borrowed_window(&external) };
assert_eq!(m.history_bytes(), &external[..]);
assert_eq!(m.history, b"owned-history-bytes");
m.clear_borrowed_window();
assert_eq!(m.history_bytes(), b"owned-history-bytes");
}
#[test]
fn reset_clears_borrowed_window() {
let mut m = FastKernelMatcher::new();
let external = b"borrowed".to_vec();
unsafe { m.set_borrowed_window(&external) };
m.reset(
FAST_LEVEL_1_WINDOW_LOG,
FAST_LEVEL_1_HASH_LOG,
FAST_LEVEL_1_MLS,
2,
false,
false,
);
assert!(m.borrowed.is_none());
assert_eq!(m.history_bytes().len(), HISTORY_DRAIN_BASE);
}
#[test]
fn borrowed_window_matches_owned_sequence_stream() {
#[derive(PartialEq, Debug)]
enum Seq {
Triple(alloc::vec::Vec<u8>, usize, usize),
Lits(alloc::vec::Vec<u8>),
}
let mut whole = alloc::vec::Vec::with_capacity(320);
for i in 0..320usize {
whole.push((i % 64) as u8);
}
let split = 192usize;
let mut owned = FastKernelMatcher::with_params(15, 12, 5, 2);
let mut owned_seqs: alloc::vec::Vec<Seq> = alloc::vec::Vec::new();
owned.accept_data(whole[..split].to_vec());
owned.start_matching(|seq| match seq {
Sequence::Triple {
literals,
offset,
match_len,
} => owned_seqs.push(Seq::Triple(literals.to_vec(), offset, match_len)),
Sequence::Literals { literals } => owned_seqs.push(Seq::Lits(literals.to_vec())),
});
owned.accept_data(whole[split..].to_vec());
owned.start_matching(|seq| match seq {
Sequence::Triple {
literals,
offset,
match_len,
} => owned_seqs.push(Seq::Triple(literals.to_vec(), offset, match_len)),
Sequence::Literals { literals } => owned_seqs.push(Seq::Lits(literals.to_vec())),
});
let mut borrowed = FastKernelMatcher::with_params(15, 12, 5, 2);
let mut borrowed_seqs: alloc::vec::Vec<Seq> = alloc::vec::Vec::new();
unsafe { borrowed.set_borrowed_window(&whole) };
borrowed.start_matching_borrowed(0, split, |seq| match seq {
Sequence::Triple {
literals,
offset,
match_len,
} => borrowed_seqs.push(Seq::Triple(literals.to_vec(), offset, match_len)),
Sequence::Literals { literals } => borrowed_seqs.push(Seq::Lits(literals.to_vec())),
});
borrowed.start_matching_borrowed(split, whole.len(), |seq| match seq {
Sequence::Triple {
literals,
offset,
match_len,
} => borrowed_seqs.push(Seq::Triple(literals.to_vec(), offset, match_len)),
Sequence::Literals { literals } => borrowed_seqs.push(Seq::Lits(literals.to_vec())),
});
assert_eq!(
owned_seqs, borrowed_seqs,
"borrowed window must emit the identical sequence stream as the owned path",
);
assert_eq!(
owned.rep, borrowed.rep,
"rep state must match after both scans"
);
assert_eq!(
owned.offset_hist, borrowed.offset_hist,
"offset_hist must match after both scans",
);
assert!(
borrowed_seqs.iter().any(|s| matches!(s, Seq::Triple(..))),
"pattern must yield at least one match to make the check meaningful",
);
}
#[test]
fn with_params_threads_through_each_field() {
let m = FastKernelMatcher::with_params(16, 12, 5, 2);
assert_eq!(m.window_log, 16);
assert_eq!(m.hash_table.hash_log(), 12);
assert_eq!(m.hash_table.mls(), 5);
assert_eq!(m.max_window_size, 1usize << 16);
}
#[test]
fn window_size_reports_one_shifted_window_log() {
let m = FastKernelMatcher::with_params(16, 12, 5, 2);
assert_eq!(m.window_size(), 1u64 << 16);
let m = FastKernelMatcher::with_params(22, 14, 7, 2);
assert_eq!(m.window_size(), 1u64 << 22);
}
#[test]
fn last_committed_space_empty_before_commit() {
let m = FastKernelMatcher::new();
assert!(m.last_committed_space().is_empty());
}
#[test]
fn reset_clears_history_and_state() {
let mut m = FastKernelMatcher::new();
m.history.extend_from_slice(&[1, 2, 3, 4]);
m.prefix_start_index = 7;
m.rep = [42, 99];
m.offset_hist = [10, 20, 30];
m.pending = Some(alloc::vec![5, 6, 7]);
m.reset(
FAST_LEVEL_1_WINDOW_LOG,
FAST_LEVEL_1_HASH_LOG,
FAST_LEVEL_1_MLS,
2,
false,
false,
);
assert_eq!(m.history.len(), HISTORY_DRAIN_BASE);
assert_eq!(m.prefix_start_index, INITIAL_PREFIX_START_INDEX);
assert_eq!(m.rep, FAST_INITIAL_REP);
assert_eq!(m.offset_hist, FAST_INITIAL_OFFSET_HIST);
assert!(m.pending.is_none());
assert_eq!(m.hash_table.hash_log(), FAST_LEVEL_1_HASH_LOG);
assert_eq!(m.hash_table.mls(), FAST_LEVEL_1_MLS);
}
#[test]
fn reset_with_changed_params_rebuilds_hash_table() {
let mut m = FastKernelMatcher::new();
m.reset(16, 10, 4, 2, false, false);
assert_eq!(m.hash_table.hash_log(), 10);
assert_eq!(m.hash_table.mls(), 4);
assert_eq!(m.window_log, 16);
assert_eq!(m.max_window_size, 1usize << 16);
}
#[test]
fn reset_keeps_table_when_overwritten_by_restore() {
let mut m = FastKernelMatcher::new();
m.reset(16, 10, 4, 2, false, false);
let probe_hash = 7u32;
unsafe { m.hash_table.put(probe_hash, 0xCAFE) };
m.reset(16, 10, 4, 2, false, true);
assert_eq!(
unsafe { m.hash_table.get(probe_hash) },
0xCAFE,
"restore-pending reset must not clear the table"
);
m.reset(16, 10, 4, 2, false, false);
assert_eq!(
unsafe { m.hash_table.get(probe_hash) },
0,
"plain reset must clear the table"
);
unsafe { m.hash_table.put(probe_hash, 0xCAFE) };
m.reset(16, 11, 4, 2, false, true);
assert_eq!(m.hash_table.hash_log(), 11);
assert_eq!(
unsafe { m.hash_table.get(probe_hash) },
0,
"shape change must rebuild the table regardless of the flag"
);
}
#[test]
fn accept_then_start_matching_emits_match_for_repeated_run() {
let mut data = alloc::vec::Vec::with_capacity(64);
for i in 0..32u8 {
data.push(i.wrapping_mul(7).wrapping_add(13));
}
data.extend_from_within(0..32);
let mut m = FastKernelMatcher::with_params(12, 8, 4, 2);
m.accept_data(data.clone());
let mut emitted_match_lens: alloc::vec::Vec<usize> = alloc::vec::Vec::new();
let mut emitted_literal_byte_count: usize = 0;
let mut tail_byte_count: usize = 0;
m.start_matching(|seq| match seq {
Sequence::Triple {
literals,
offset: _,
match_len,
} => {
emitted_literal_byte_count += literals.len();
emitted_match_lens.push(match_len);
}
Sequence::Literals { literals } => {
tail_byte_count += literals.len();
}
});
let total_matched: usize = emitted_match_lens.iter().sum();
assert_eq!(
emitted_literal_byte_count + total_matched + tail_byte_count,
data.len(),
"all input bytes must be accounted for as literals/matches/tail",
);
assert!(
emitted_match_lens.iter().any(|&m| m >= 4),
"kernel must emit at least one Triple with match_len >= MIN_MATCH (got {emitted_match_lens:?})",
);
assert!(m.pending.is_none());
assert_eq!(m.history.len(), data.len() + HISTORY_DRAIN_BASE);
assert_eq!(m.last_committed_space(), data.as_slice());
}
#[test]
fn skip_matching_extends_history_without_emissions() {
let mut m = FastKernelMatcher::with_params(12, 8, 4, 2);
let pre_rep = m.rep;
let pre_offset_hist = m.offset_hist;
let payload: alloc::vec::Vec<u8> = (0..40u8).collect();
m.accept_data(payload.clone());
assert_eq!(m.last_committed_space().len(), payload.len());
m.skip_matching_with_hint(None);
assert_eq!(
m.history.len(),
payload.len() + HISTORY_DRAIN_BASE,
"skip_matching must append the pending buffer to history",
);
assert_eq!(m.rep, pre_rep, "skip must not touch rep state");
assert_eq!(
m.offset_hist, pre_offset_hist,
"skip must not touch offset_hist",
);
assert!(m.pending.is_none());
}
#[test]
fn cross_block_match_finds_first_block_payload() {
let mut block1 = alloc::vec::Vec::with_capacity(128);
for i in 0..128u8 {
block1.push(i.wrapping_mul(11).wrapping_add(5));
}
let mut block2 = alloc::vec::Vec::with_capacity(64);
block2.extend(0..16u8); block2.extend_from_slice(&block1[0..32]); block2.extend(200..216u8);
let mut m = FastKernelMatcher::with_params(12, 8, 4, 2);
m.accept_data(block1.clone());
m.start_matching(|_seq| {});
m.accept_data(block2.clone());
let mut max_match: usize = 0;
let mut saw_cross_block = false;
m.start_matching(|seq| {
if let Sequence::Triple {
offset, match_len, ..
} = seq
{
max_match = max_match.max(match_len);
if offset >= block2.len() {
saw_cross_block = true;
}
}
});
assert!(
saw_cross_block,
"block 2's matcher must find at least one cross-block match \
(max_len={max_match})",
);
assert_eq!(
m.history.len(),
block1.len() + block2.len() + HISTORY_DRAIN_BASE,
"history must hold both blocks after two start_matching calls",
);
}
#[test]
fn skip_matching_with_false_hint_populates_hashes_for_dict_priming() {
let mut dict_block = alloc::vec::Vec::with_capacity(32);
for i in 0..32u8 {
dict_block.push(i.wrapping_mul(13).wrapping_add(7));
}
let mut m = FastKernelMatcher::with_params(12, 8, 4, 2);
m.accept_data(dict_block.clone());
m.skip_matching_with_hint(Some(false));
assert_eq!(m.history.len(), dict_block.len() + HISTORY_DRAIN_BASE);
assert_eq!(m.prefix_start_index, INITIAL_PREFIX_START_INDEX);
let mut block2 = alloc::vec::Vec::with_capacity(48);
block2.extend(100..116u8);
block2.extend_from_slice(&dict_block[0..16]);
block2.extend(120..136u8);
m.accept_data(block2.clone());
let mut saw_cross_block = false;
m.start_matching(|seq| {
if let Sequence::Triple { offset, .. } = seq
&& offset >= block2.len()
{
saw_cross_block = true;
}
});
assert!(
saw_cross_block,
"skip_matching(Some(false)) must populate hashes so block 2 \
can match against the primed bytes",
);
}
#[test]
fn skip_matching_with_none_hint_skips_hash_population() {
let mut dict_block = alloc::vec::Vec::with_capacity(32);
for i in 0..32u8 {
dict_block.push(i.wrapping_mul(13).wrapping_add(7));
}
let mut m = FastKernelMatcher::with_params(12, 8, 4, 2);
m.accept_data(dict_block.clone());
m.skip_matching_with_hint(None);
let mut block2 = alloc::vec::Vec::with_capacity(48);
block2.extend(100..116u8);
block2.extend_from_slice(&dict_block[0..16]);
block2.extend(120..136u8);
m.accept_data(block2.clone());
let mut saw_cross_block = false;
m.start_matching(|seq| {
if let Sequence::Triple { offset, .. } = seq
&& offset >= block2.len()
{
saw_cross_block = true;
}
});
assert!(
!saw_cross_block,
"skip_matching(None) must NOT populate hashes — the legacy \
skip cost-savings only hold when future blocks are willing \
to miss matches in the skipped region",
);
}
#[test]
fn extend_history_drains_old_prefix_past_two_window_sizes() {
let mut m = FastKernelMatcher::with_params(8, 6, 4, 2);
for round in 0..3 {
let block: alloc::vec::Vec<u8> = (0..200u8)
.map(|i| i.wrapping_add(round as u8 * 17))
.collect();
m.accept_data(block);
m.skip_matching_with_hint(None);
}
assert!(
m.history.len() <= m.max_window_size * 2 + HISTORY_DRAIN_BASE,
"after eviction, REAL history must be bounded by 2× \
max_window_size (got history.len()={}, max_window_size={})",
m.history.len(),
m.max_window_size,
);
assert!(
m.history.len() <= m.max_window_size + 200 + HISTORY_DRAIN_BASE,
"post-append history = retained prefix (≤ max_window_size) \
+ last block (200 bytes); got {}",
m.history.len(),
);
assert_eq!(
m.prefix_start_index, INITIAL_PREFIX_START_INDEX,
"drain must rebase prefix_start_index to the baseline (1)",
);
}
#[test]
fn skip_matching_dict_prime_handles_exactly_hash_read_size_bytes() {
let mut m = FastKernelMatcher::with_params(12, 8, 4, 2);
let payload: alloc::vec::Vec<u8> = (0..8u8).collect();
m.accept_data(payload);
m.skip_matching_with_hint(Some(false));
assert_eq!(m.history.len(), 8 + HISTORY_DRAIN_BASE);
}
#[test]
fn skip_matching_dict_prime_handles_below_hash_read_size_bytes() {
let mut m = FastKernelMatcher::with_params(12, 8, 4, 2);
let payload: alloc::vec::Vec<u8> = (0..4u8).collect();
m.accept_data(payload);
m.skip_matching_with_hint(Some(false));
assert_eq!(m.history.len(), 4 + HISTORY_DRAIN_BASE);
}
#[test]
fn dict_prime_indexes_positions_across_chunk_seam() {
let mut m = FastKernelMatcher::with_params(20, 20, 4, 2);
let chunk1: alloc::vec::Vec<u8> = (0..16u8)
.map(|i| i.wrapping_mul(37).wrapping_add(13))
.collect();
m.accept_data(chunk1);
m.skip_matching_for_dict_prime();
let seam = m.history.len(); let chunk2: alloc::vec::Vec<u8> = (16..32u8)
.map(|i| i.wrapping_mul(37).wrapping_add(13))
.collect();
m.accept_data(chunk2);
m.skip_matching_for_dict_prime();
let p = seam - 4;
let dt = m.dict.table().expect("dict table primed");
let found = unsafe {
crate::encoding::simple::fast_kernel::kernel::dict_lookup::<4>(
dt,
m.history.as_ptr().add(p),
dt.hash_log(),
)
};
assert_eq!(
found, p as u32,
"seam-spanning position {p} must be indexed in the dict table",
);
}
#[test]
fn block_samples_match_dict_fires_only_on_extendable_dict_match() {
let dict: alloc::vec::Vec<u8> = (0..200u8)
.map(|i| i.wrapping_mul(37).wrapping_add(13))
.collect();
let mut m = FastKernelMatcher::with_params(20, 20, 4, 2);
m.accept_data(dict.clone());
m.skip_matching_for_dict_prime();
assert!(m.dict_is_attached(), "dict must be attached after prime");
let hit = dict[8..40].to_vec();
assert!(
m.block_samples_match_dict(&hit),
"a long verbatim dict run must trip the dict probe",
);
let mut short = dict[8..16].to_vec();
short.extend((0..56u8).map(|i| i.wrapping_mul(53).wrapping_add(201)));
assert!(
!m.block_samples_match_dict(&short),
"a sub-16-byte dict match must not trip the probe",
);
let miss: alloc::vec::Vec<u8> = (0..64u8)
.map(|i| i.wrapping_mul(91).wrapping_add(7) ^ 0xA5)
.collect();
assert!(
!m.block_samples_match_dict(&miss),
"a non-dict block must not trip the probe",
);
assert!(
!m.block_samples_match_dict(&dict[..4]),
"a sub-8-byte block cannot be probed",
);
}
#[test]
fn block_samples_match_dict_is_false_without_a_dictionary() {
let m = FastKernelMatcher::with_params(20, 20, 4, 2);
let block: alloc::vec::Vec<u8> = (0..64u8)
.map(|i| i.wrapping_mul(37).wrapping_add(13))
.collect();
assert!(!m.dict_is_attached());
assert!(!m.block_samples_match_dict(&block));
}
#[test]
fn main_table_prime_indexes_positions_across_slice_seam() {
let mut m = FastKernelMatcher::with_params(20, 20, 4, 2);
let chunk1: alloc::vec::Vec<u8> = (0..16u8)
.map(|i| i.wrapping_mul(53).wrapping_add(7))
.collect();
m.accept_data(chunk1);
m.skip_matching_with_hint(Some(false));
let seam = m.history.len();
let chunk2: alloc::vec::Vec<u8> = (16..32u8)
.map(|i| i.wrapping_mul(53).wrapping_add(7))
.collect();
m.accept_data(chunk2);
m.skip_matching_with_hint(Some(false));
let p = seam - 4;
let h = unsafe { m.hash_table.hash_ptr::<4>(m.history.as_ptr().add(p)) };
assert_eq!(
unsafe { m.hash_table.get(h) },
p as u32,
"seam-spanning position {p} must be indexed in the main table",
);
}
#[test]
fn rep_tracks_last_explicit_offset_and_offset_hist_is_not_matched() {
let mut data = alloc::vec::Vec::with_capacity(96);
for i in 0..48u8 {
data.push(i.wrapping_mul(11).wrapping_add(3));
}
data.extend_from_within(0..48);
let mut m = FastKernelMatcher::with_params(12, 8, 4, 2);
m.accept_data(data.clone());
let mut emitted_offsets: alloc::vec::Vec<usize> = alloc::vec::Vec::new();
m.start_matching(|seq| {
if let Sequence::Triple {
offset, match_len, ..
} = seq
&& match_len >= 4
{
emitted_offsets.push(offset);
}
});
assert!(
!emitted_offsets.is_empty(),
"test setup must produce at least one explicit match",
);
let last_explicit = emitted_offsets[emitted_offsets.len() - 1];
assert_eq!(
m.rep[0] as usize, last_explicit,
"kernel's rep[0] must reflect the last emitted explicit offset",
);
assert_eq!(
m.offset_hist, FAST_INITIAL_OFFSET_HIST,
"Fast matching must not mutate offset_hist (it is seeded only \
by reset / prime_offset_history; the wire offset coding runs \
downstream against the encode pipeline's own history)",
);
}
#[test]
fn eviction_during_dict_priming_drops_stale_prime_entries() {
let mut m = FastKernelMatcher::with_params(8, 6, 4, 2);
let block1: alloc::vec::Vec<u8> = (0..200u8).collect();
m.accept_data(block1);
m.skip_matching_with_hint(Some(false));
let block2: alloc::vec::Vec<u8> = (0..200u8).map(|i| i.wrapping_add(50)).collect();
m.accept_data(block2);
m.skip_matching_with_hint(Some(false));
let block3: alloc::vec::Vec<u8> = (0..200u8).map(|i| i.wrapping_add(100)).collect();
m.accept_data(block3);
m.skip_matching_with_hint(Some(false));
assert_eq!(
m.prefix_start_index, INITIAL_PREFIX_START_INDEX,
"drain must rebase prefix_start_index to the baseline (1)",
);
assert!(m.history.len() <= m.max_window_size * 2);
}
#[test]
fn accept_data_evicts_eagerly_so_commit_observes_byte_delta() {
let mut m = FastKernelMatcher::with_params(8, 6, 4, 2);
m.accept_data((0..200u8).collect());
m.skip_matching_with_hint(None);
assert_eq!(m.history.len(), 200 + HISTORY_DRAIN_BASE);
assert_eq!(
m.prefix_start_index, INITIAL_PREFIX_START_INDEX,
"no eviction yet"
);
m.accept_data((0..200u8).map(|i| i.wrapping_add(50)).collect());
m.skip_matching_with_hint(None);
assert_eq!(m.history.len(), 400 + HISTORY_DRAIN_BASE);
assert_eq!(
m.prefix_start_index, INITIAL_PREFIX_START_INDEX,
"still no eviction (400 < 512)",
);
let pre = m.history_len_for_eviction_accounting();
m.accept_data((0..200u8).map(|i| i.wrapping_add(100)).collect());
let post = m.history_len_for_eviction_accounting();
assert!(
pre > post,
"accept_data must shrink history at the eviction threshold \
(pre={pre}, post={post}) — driver's commit_space relies on \
this delta for retire_dictionary_budget accounting",
);
assert_eq!(
post, 256,
"post-eviction retained must equal max_window_size",
);
assert_eq!(
m.prefix_start_index, INITIAL_PREFIX_START_INDEX,
"drain rebases prefix_start_index to INITIAL_PREFIX_START_INDEX \
— eviction is proven by the history.len() shrink above",
);
}
#[test]
fn trim_to_window_keeps_last_committed_space_consistent() {
let mut m = FastKernelMatcher::with_params(8, 6, 4, 2);
let payload: alloc::vec::Vec<u8> = (0..200u8).collect();
m.accept_data(payload);
m.skip_matching_with_hint(None);
assert_eq!(m.last_block_start, HISTORY_DRAIN_BASE);
assert_eq!(m.history.len(), 200 + HISTORY_DRAIN_BASE);
let payload2: alloc::vec::Vec<u8> = (50..150u8).collect();
m.accept_data(payload2);
m.skip_matching_with_hint(None);
assert_eq!(m.last_block_start, HISTORY_DRAIN_BASE + 200);
assert_eq!(m.history.len(), 300 + HISTORY_DRAIN_BASE);
m.max_window_size = 64;
let drained = m.trim_to_window();
assert_eq!(
drained,
300 - 64,
"trim must drain REAL history down to max_window_size = 64",
);
assert_eq!(m.history.len(), 64 + HISTORY_DRAIN_BASE);
let last = m.last_committed_space();
assert!(
last.len() <= 64,
"last_committed_space must be in-bounds after trim \
(got len {})",
last.len(),
);
}
#[test]
fn prime_offset_history_keeps_rep_and_offset_hist_in_lockstep() {
let mut m = FastKernelMatcher::with_params(12, 8, 4, 2);
assert_eq!(m.rep, FAST_INITIAL_REP);
assert_eq!(m.offset_hist, FAST_INITIAL_OFFSET_HIST);
let primed = [9u32, 4, 8];
m.prime_offset_history(primed);
assert_eq!(
m.offset_hist, primed,
"offset_hist must be updated by prime_offset_history",
);
assert_eq!(
m.rep,
[primed[0], primed[1]],
"rep[0..2] must mirror offset_hist[0..2] post-prime \
(kernel's repcode decisions must match the wire \
encoder's seeded history)",
);
}
#[test]
fn accept_data_evicts_more_aggressively_when_block_larger_than_window() {
let mut m = FastKernelMatcher::with_params(8, 6, 4, 2);
let preamble: alloc::vec::Vec<u8> = (0..256u32).map(|i| i as u8).collect();
m.accept_data(preamble);
m.skip_matching_with_hint(None);
assert_eq!(
m.history_len_for_eviction_accounting(),
256,
"history pre-filled to one full window of real bytes",
);
let oversize: alloc::vec::Vec<u8> = (0..400u32)
.map(|i| (i as u8).wrapping_mul(7).wrapping_add(11))
.collect();
m.accept_data(oversize);
let real_len_after = m.history_len_for_eviction_accounting();
m.start_matching(|_| {});
let real_total = m.history_len_for_eviction_accounting();
assert!(
real_total <= m.max_window_size * 2,
"post-append history MUST stay within 2 × max_window_size \
(got real_total={real_total}, cap={})",
m.max_window_size * 2,
);
assert!(
real_len_after < 256,
"pre-append drain must have shed historical bytes \
(got real_len_after_drain={real_len_after}, was 256 \
before accept)",
);
}
#[test]
fn start_matching_enforces_max_window_size_offset_bound() {
let mut m = FastKernelMatcher::with_params(7, 8, 4, 2);
let max_window = m.max_window_size;
assert_eq!(max_window, 128, "test assumes window_log=7");
let block1: alloc::vec::Vec<u8> = (0..200u8).map(|i| 0x30 + (i % 64)).collect();
m.accept_data(block1.clone());
m.start_matching(|_| {});
let block2 = block1.clone();
m.accept_data(block2);
let mut max_emitted_offset = 0usize;
let mut emitted_match_count = 0usize;
m.start_matching(|seq| {
if let Sequence::Triple {
offset, match_len, ..
} = seq
&& match_len > 0
{
emitted_match_count += 1;
if offset > max_emitted_offset {
max_emitted_offset = offset;
}
}
});
assert!(
emitted_match_count > 0,
"fixture must produce at least one Triple match — \
history.len()=~400, max_window=128, block2 is identical to block1",
);
assert!(
max_emitted_offset <= max_window,
"sliding floor MUST cap emitted offsets at max_window_size; \
got max emitted offset {} vs max_window_size {}",
max_emitted_offset,
max_window,
);
}
#[test]
fn start_matching_caps_offsets_at_window_log_not_inflated_max() {
let mut m = FastKernelMatcher::with_params(7, 8, 4, 2);
let advertised_window: usize = 1 << m.window_log;
assert_eq!(advertised_window, 128, "test assumes window_log=7");
let dict: alloc::vec::Vec<u8> = (0..200u8).map(|i| 0x40 + (i % 4)).collect();
m.accept_data(dict.clone());
m.start_matching(|_| {}); m.max_window_size = m.max_window_size.saturating_add(200);
let block: alloc::vec::Vec<u8> = (0..100u8).map(|i| 0x40 + (i % 4)).collect();
m.accept_data(block);
let mut max_emitted_offset = 0usize;
let mut emitted_match_count = 0usize;
m.start_matching(|seq| {
if let Sequence::Triple {
offset, match_len, ..
} = seq
&& match_len > 0
{
emitted_match_count += 1;
if offset > max_emitted_offset {
max_emitted_offset = offset;
}
}
});
assert!(
emitted_match_count > 0,
"fixture must produce at least one match — block content \
repeats dict, history.len() ≈ 300, scan should find at \
least one Triple",
);
assert!(
max_emitted_offset <= advertised_window,
"sliding floor MUST cap emitted offsets at the ADVERTISED \
frame window (1 << window_log = {}), NOT the inflated \
max_window_size; got max emitted offset {}",
advertised_window,
max_emitted_offset,
);
}
#[test]
fn block_zero_prologue_preserves_default_rep_offset_one() {
let mut data = alloc::vec::Vec::with_capacity(200);
data.push(0x01);
data.resize(200, 0x42);
let mut m = FastKernelMatcher::with_params(12, 8, 4, 2);
m.accept_data(data.clone());
let mut first_literals_len: Option<usize> = None;
let mut first_offset: Option<usize> = None;
m.start_matching(|seq| {
if first_literals_len.is_some() {
return;
}
if let Sequence::Triple {
literals, offset, ..
} = seq
{
first_literals_len = Some(literals.len());
first_offset = Some(offset);
}
});
assert_eq!(
first_offset,
Some(1),
"first emit must reference offset=1 — upstream zstd's default \
rep_offset1=1 fires on rep-at-ip2 at iter 1, and the \
prologue MUST NOT zero it (max_rep computed against \
window_low=0 at block 0, NOT against the sentinel \
prefix=1)",
);
assert_eq!(
first_literals_len,
Some(2),
"first emit must have a 2-byte literal prefix \
([0x01, 0x42]) — the rep-at-ip2 probe lands at ip2=3, \
then the one-byte backward extension drops new_ip to 2, \
so literals = data[0..2]. A different prefix length \
would indicate the explicit-match catch-up fired instead",
);
}