use super::*;
use alloc::vec;
use std::format;
fn lines(count: u32) -> (Vec<u8>, Vec<usize>) {
let mut data = Vec::new();
let mut sizes = Vec::new();
for i in 0..count {
let line =
format!("tenant=demo table=orders key={i} region=eu payload=aaaaabbbbbccccdddd\n");
sizes.push(line.len());
data.extend_from_slice(line.as_bytes());
}
(data, sizes)
}
#[test]
fn dmers_are_counted_inside_their_sample_only() {
let data: Vec<u8> = (0u8..45).collect();
let set = SampleSet::new(&data, &[9; 5]).unwrap();
let ctx = FastCoverContext::new(&set, 5, 8, 20, 1).unwrap();
assert_eq!(ctx.freqs.iter().map(|&c| u64::from(c)).sum::<u64>(), 10);
assert_eq!(ctx.nb_dmers, 45 - 8 + 1);
}
#[test]
fn accel_strides_the_count_and_shrinks_the_finalize_share() {
let data: Vec<u8> = (0u8..60).collect();
let set = SampleSet::new(&data, &[12; 5]).unwrap();
let full = FastCoverContext::new(&set, 5, 8, 20, 1).unwrap();
let strided = FastCoverContext::new(&set, 5, 8, 20, 2).unwrap();
let total = |ctx: &FastCoverContext<'_>| ctx.freqs.iter().map(|&c| u64::from(c)).sum::<u64>();
assert_eq!(total(&full), 25);
assert_eq!(total(&strided), 15);
assert_eq!(finalize_samples(100, 1), 100);
assert_eq!(finalize_samples(100, 2), 50);
assert_eq!(finalize_samples(100, 10), 10);
}
#[test]
fn training_bytes_shorter_than_a_dmer_are_refused() {
let data = [1u8; 7];
let set = SampleSet::new(&data, &[1, 1, 1, 1, 3]).unwrap();
let err = FastCoverContext::new(&set, 5, 6, 20, 1).err().unwrap();
assert_eq!(err.kind(), io::ErrorKind::InvalidInput);
}
#[test]
fn build_fills_at_most_the_capacity_from_the_training_bytes() {
let (data, sizes) = lines(500);
let set = SampleSet::new(&data, &sizes).unwrap();
let ctx = FastCoverContext::new(&set, sizes.len(), 8, 20, 1).unwrap();
let mut window = WindowCounts::default();
let mut freqs = Vec::new();
let mut out = Vec::new();
let content = ctx
.build(&mut freqs, &mut window, &mut out, 4096, 256)
.unwrap()
.to_vec();
assert!(!content.is_empty() && content.len() <= 4096);
let last = &content[content.len() - 8..];
assert!(data.windows(8).any(|w| w == last));
let again = ctx
.build(&mut freqs, &mut window, &mut out, 4096, 256)
.unwrap();
assert_eq!(content, again);
}
#[test]
fn a_segment_longer_than_a_16_bit_count_trains() {
let k = 66_000;
let data = vec![0u8; 10 * k + 1000];
let each = data.len() / 5;
let set = SampleSet::new(&data, &[each; 5]).unwrap();
let ctx = FastCoverContext::new(&set, 5, 8, 20, 1).unwrap();
let mut out = Vec::new();
let content = ctx
.build(
&mut Vec::new(),
&mut WindowCounts::default(),
&mut out,
k,
k,
)
.unwrap();
assert_eq!(content, [0u8; 8]);
}
#[test]
fn a_segment_longer_than_the_corpus_trains() {
let (data, sizes) = lines(100);
let set = SampleSet::new(&data, &sizes).unwrap();
let ctx = FastCoverContext::new(&set, sizes.len(), 8, 20, 1).unwrap();
let mut out = Vec::new();
let content = ctx
.build(
&mut Vec::new(),
&mut WindowCounts::default(),
&mut out,
4096,
usize::MAX / 4,
)
.unwrap();
assert!(!content.is_empty() && content.len() <= 4096);
}
#[test]
fn every_table_width_trains() {
let (data, sizes) = lines(200);
let set = SampleSet::new(&data, &sizes).unwrap();
let mut freqs = Vec::new();
let mut out = Vec::new();
for f in [1, 4, 8, 24] {
let ctx = FastCoverContext::new(&set, sizes.len(), 8, f, 1).unwrap();
assert_eq!(ctx.freqs.len(), 1 << f);
let content = ctx
.build(
&mut freqs,
&mut WindowCounts::default(),
&mut out,
2048,
128,
)
.unwrap();
assert!(!content.is_empty(), "f={f}");
}
}
#[test]
fn a_count_table_that_does_not_fit_is_an_error() {
let entries = usize::MAX / 2;
assert_eq!(
zeroed_counts::<u32>(entries).unwrap_err(),
TableTooLarge { entries }
);
#[cfg(target_pointer_width = "64")]
{
let entries = isize::MAX as usize / 4;
assert_eq!(
zeroed_counts::<u32>(entries).unwrap_err(),
TableTooLarge { entries }
);
}
let table = zeroed_counts::<u16>(1 << 12).unwrap();
assert_eq!(table.len(), 1 << 12);
assert!(table.iter().all(|&count| count == 0));
assert!(zeroed_counts::<u16>(0).unwrap().is_empty());
}
#[test]
fn a_table_that_does_not_fit_is_an_out_of_memory_error() {
let err = io::Error::from(TableTooLarge { entries: 1 << 31 });
assert_eq!(err.kind(), io::ErrorKind::OutOfMemory);
let message = std::string::ToString::to_string(&err);
assert!(message.contains("2147483648 entries"), "{message}");
assert!(message.contains("smaller f"), "{message}");
}