use std::io::Write;
use ordvec::{Bitmap, Rank, RankQuant, SignBitmap};
use crate::{make_corpus, D, N};
fn read_bytes(p: &std::path::Path) -> Vec<u8> {
std::fs::read(p).unwrap()
}
fn write_bytes(p: &std::path::Path, b: &[u8]) {
std::fs::File::create(p).unwrap().write_all(b).unwrap();
}
fn tmp(name: &str) -> std::path::PathBuf {
std::env::temp_dir().join(format!(
"ordvec_loadval_{}_{}.bin",
name,
std::process::id()
))
}
#[test]
fn load_rank_rejects_non_permutation_row() {
let corpus = make_corpus(1);
let mut idx = Rank::new(D);
idx.add(&corpus);
let p = tmp("rank_perm");
idx.write(&p).unwrap();
assert!(Rank::load(&p).is_ok(), "valid Rank file must load");
let mut bytes = read_bytes(&p);
let (a, b) = (13usize, 15usize); bytes[b] = bytes[a];
bytes[b + 1] = bytes[a + 1];
write_bytes(&p, &bytes);
let r = Rank::load(&p);
std::fs::remove_file(&p).ok();
assert!(
r.is_err(),
"Rank::load must reject a row that is not a permutation of [0, dim)"
);
}
#[test]
fn load_rankquant_rejects_skewed_composition() {
let corpus = make_corpus(2);
let mut idx = RankQuant::new(D, 2);
idx.add(&corpus);
let p = tmp("rq_comp");
idx.write(&p).unwrap();
assert!(
RankQuant::load(&p).is_ok(),
"valid RankQuant file must load"
);
let mut bytes = read_bytes(&p);
for byte in bytes.iter_mut().skip(14) {
*byte = 0;
}
write_bytes(&p, &bytes);
let r = RankQuant::load(&p);
std::fs::remove_file(&p).ok();
assert!(
r.is_err(),
"RankQuant::load must reject a document whose bucket composition is not uniform"
);
}
#[test]
fn load_bitmap_rejects_wrong_popcount_row() {
let corpus = make_corpus(3);
let n_top = D / 4;
let mut idx = Bitmap::new(D, n_top);
idx.add(&corpus);
let p = tmp("bm_pop");
idx.write(&p).unwrap();
assert!(Bitmap::load(&p).is_ok(), "valid Bitmap file must load");
let qpv = D / 64;
let mut bytes = read_bytes(&p);
for byte in bytes.iter_mut().skip(17).take(qpv * 8) {
*byte = 0;
}
write_bytes(&p, &bytes);
let r = Bitmap::load(&p);
std::fs::remove_file(&p).ok();
assert!(
r.is_err(),
"Bitmap::load must reject a document whose popcount != n_top"
);
}
#[test]
fn load_sign_bitmap_accepts_any_bit_pattern() {
let corpus = make_corpus(4);
let mut idx = SignBitmap::new(D);
idx.add(&corpus);
let p = tmp("sb_any");
idx.write(&p).unwrap();
let mut bytes = read_bytes(&p);
for byte in bytes.iter_mut().skip(13) {
*byte ^= 0xAA;
}
write_bytes(&p, &bytes);
let loaded = SignBitmap::load(&p);
std::fs::remove_file(&p).ok();
let loaded = loaded.expect("SignBitmap::load must accept any bit pattern");
assert_eq!(
loaded.len(),
N,
"sign bitmap doc count preserved after edit"
);
}
#[test]
fn loaders_reject_trailing_bytes() {
let corpus = make_corpus(5);
let n_top = D / 4;
{
let mut idx = Rank::new(D);
idx.add(&corpus);
let p = tmp("rank_trail");
idx.write(&p).unwrap();
assert!(Rank::load(&p).is_ok(), "valid Rank file must load");
let mut bytes = read_bytes(&p);
bytes.push(0x00);
write_bytes(&p, &bytes);
let r = Rank::load(&p);
std::fs::remove_file(&p).ok();
assert!(r.is_err(), "Rank::load must reject trailing bytes");
}
{
let mut idx = RankQuant::new(D, 2);
idx.add(&corpus);
let p = tmp("rq_trail");
idx.write(&p).unwrap();
assert!(
RankQuant::load(&p).is_ok(),
"valid RankQuant file must load"
);
let mut bytes = read_bytes(&p);
bytes.push(0x00);
write_bytes(&p, &bytes);
let r = RankQuant::load(&p);
std::fs::remove_file(&p).ok();
assert!(r.is_err(), "RankQuant::load must reject trailing bytes");
}
{
let mut idx = Bitmap::new(D, n_top);
idx.add(&corpus);
let p = tmp("bm_trail");
idx.write(&p).unwrap();
assert!(Bitmap::load(&p).is_ok(), "valid Bitmap file must load");
let mut bytes = read_bytes(&p);
bytes.push(0x00);
write_bytes(&p, &bytes);
let r = Bitmap::load(&p);
std::fs::remove_file(&p).ok();
assert!(r.is_err(), "Bitmap::load must reject trailing bytes");
}
{
let mut idx = SignBitmap::new(D);
idx.add(&corpus);
let p = tmp("sb_trail");
idx.write(&p).unwrap();
assert!(
SignBitmap::load(&p).is_ok(),
"valid SignBitmap file must load"
);
let mut bytes = read_bytes(&p);
bytes.push(0x00);
write_bytes(&p, &bytes);
let r = SignBitmap::load(&p);
std::fs::remove_file(&p).ok();
assert!(r.is_err(), "SignBitmap::load must reject trailing bytes");
}
}