use crate::contiguous_file_arena::DATA_OFFSET;
use crate::perf_optimizations::ContiguousVectors;
use tempfile::tempdir;
fn vector(dimension: usize, seed: usize) -> Vec<f32> {
(0..dimension)
.map(|d| {
let raw = u16::try_from((seed * dimension + d) % 65_536).expect("fits u16");
f32::from(raw)
})
.collect()
}
fn fill(storage: &mut ContiguousVectors, n: usize, dimension: usize) -> Vec<Vec<f32>> {
let written: Vec<Vec<f32>> = (0..n).map(|i| vector(dimension, i)).collect();
for v in &written {
storage.push(v).expect("push");
}
written
}
fn assert_contents(storage: &ContiguousVectors, expected: &[Vec<f32>]) {
assert_eq!(storage.len(), expected.len(), "vector count");
for (i, want) in expected.iter().enumerate() {
assert_eq!(
storage.get(i).expect("slot present"),
want.as_slice(),
"slot {i} content"
);
}
}
#[test]
fn file_backed_matches_heap_backed_contents() {
let dir = tempdir().expect("tempdir");
let dimension = 32;
let mut heap = ContiguousVectors::new(dimension, 16).expect("heap arena");
let mut mapped = ContiguousVectors::new_file_backed(&dir.path().join("a.arena"), dimension, 16)
.expect("file arena");
let written = fill(&mut mapped, 40, dimension);
for v in &written {
heap.push(v).expect("push");
}
assert_contents(&mapped, &written);
assert_eq!(
mapped.as_flat_slice(),
heap.as_flat_slice(),
"the two backings must produce byte-identical arenas"
);
}
#[test]
fn growth_preserves_every_vector_across_remap() {
let dir = tempdir().expect("tempdir");
let dimension = 8;
let mut storage =
ContiguousVectors::new_file_backed(&dir.path().join("g.arena"), dimension, 16)
.expect("file arena");
assert_eq!(storage.capacity(), 16, "starts at the requested capacity");
let written = fill(&mut storage, 500, dimension);
assert!(
storage.capacity() >= 500,
"capacity must have grown, got {}",
storage.capacity()
);
assert_contents(&storage, &written);
}
#[test]
fn grown_region_is_zero_filled() {
let dir = tempdir().expect("tempdir");
let dimension = 4;
let mut storage =
ContiguousVectors::new_file_backed(&dir.path().join("z.arena"), dimension, 16)
.expect("file arena");
storage
.insert_at(200, &vector(dimension, 200))
.expect("insert_at");
for gap in [0_usize, 1, 99, 199] {
assert_eq!(
storage.get(gap).expect("gap slot present"),
vec![0.0_f32; dimension].as_slice(),
"slot {gap} must be zero-filled, not uninitialised"
);
}
}
#[test]
fn reopening_the_file_recovers_the_arena() {
let dir = tempdir().expect("tempdir");
let path = dir.path().join("r.arena");
let dimension = 16;
let count = 50;
let written = {
let mut storage =
ContiguousVectors::new_file_backed(&path, dimension, 64).expect("file arena");
let written = fill(&mut storage, count, dimension);
storage.flush_backing().expect("flush");
written
};
let reopened =
ContiguousVectors::open_file_backed(&path, dimension, 64, count).expect("reopen");
assert_contents(&reopened, &written);
}
#[test]
fn file_reserves_a_page_before_the_data_region() {
let dir = tempdir().expect("tempdir");
let path = dir.path().join("h.arena");
let dimension = 8;
let mut storage = ContiguousVectors::new_file_backed(&path, dimension, 16).expect("file arena");
fill(&mut storage, 16, dimension);
storage.flush_backing().expect("flush");
let len = std::fs::metadata(&path).expect("metadata").len();
let data_bytes = (16 * dimension * std::mem::size_of::<f32>()) as u64;
assert_eq!(
len,
DATA_OFFSET as u64 + data_bytes,
"file is a reserved page followed by exactly the vector bytes"
);
}
#[test]
fn open_refuses_a_count_beyond_capacity() {
let dir = tempdir().expect("tempdir");
let path = dir.path().join("bad.arena");
let dimension = 4;
drop(ContiguousVectors::new_file_backed(&path, dimension, 16).expect("file arena"));
let err = ContiguousVectors::open_file_backed(&path, dimension, 16, 17)
.expect_err("count > capacity must be refused");
assert!(
err.to_string().contains("exceeds capacity"),
"error should name the violated bound, got: {err}"
);
}
#[test]
fn reorder_keeps_a_mapped_arena_mapped() {
let dir = tempdir().expect("tempdir");
let dimension = 4;
let mut storage =
ContiguousVectors::new_file_backed(&dir.path().join("o.arena"), dimension, 16)
.expect("file arena");
let written = fill(&mut storage, 4, dimension);
storage.reorder(&[3, 2, 1, 0]).expect("reorder");
let expected: Vec<Vec<f32>> = written.iter().rev().cloned().collect();
assert_contents(&storage, &expected);
assert!(
format!("{storage:?}").contains("FileMapped"),
"arena must still be file-mapped after a reorder, got: {storage:?}"
);
assert_eq!(storage.capacity(), 16, "reorder must not resize the arena");
drop(storage);
}
#[test]
fn reorder_writes_the_new_order_through_to_the_file() {
let dir = tempdir().expect("tempdir");
let path = dir.path().join("persisted.arena");
let dimension = 4;
let mut storage = ContiguousVectors::new_file_backed(&path, dimension, 16).expect("file arena");
let written = fill(&mut storage, 4, dimension);
storage.reorder(&[3, 2, 1, 0]).expect("reorder");
storage.flush_backing().expect("flush");
let expected: Vec<f32> = written.iter().rev().flatten().copied().collect();
assert_eq!(on_disk_vectors(&path, expected.len()), expected);
}
fn on_disk_vectors(path: &std::path::Path, len: usize) -> Vec<f32> {
let bytes = std::fs::read(path).expect("read arena file");
let data = &bytes[DATA_OFFSET..];
data.chunks_exact(std::mem::size_of::<f32>())
.take(len)
.map(|c| {
let mut word = [0_u8; 4];
word.copy_from_slice(c);
f32::from_ne_bytes(word)
})
.collect()
}
#[test]
fn reorder_refuses_a_permutation_that_repeats_an_index() {
let dir = tempdir().expect("tempdir");
let dimension = 4;
let mut storage =
ContiguousVectors::new_file_backed(&dir.path().join("dup.arena"), dimension, 16)
.expect("file arena");
let written = fill(&mut storage, 4, dimension);
let err = storage
.reorder(&[0, 1, 1, 3])
.expect_err("a repeated index is not a permutation");
assert!(
err.to_string().contains("appears twice"),
"error should name the violation, got: {err}"
);
assert_contents(&storage, &written);
}
#[test]
fn reorder_agrees_between_the_two_backings() {
let dir = tempdir().expect("tempdir");
let dimension = 3;
let count = 9;
let order = [1, 2, 3, 4, 5, 6, 7, 0, 8];
let mut mapped =
ContiguousVectors::new_file_backed(&dir.path().join("cmp.arena"), dimension, 16)
.expect("file arena");
let written = fill(&mut mapped, count, dimension);
let mut heap = ContiguousVectors::new(dimension, 16).expect("heap arena");
for v in &written {
heap.push(v).expect("push");
}
mapped.reorder(&order).expect("reorder mapped");
heap.reorder(&order).expect("reorder heap");
let expected: Vec<Vec<f32>> = order.iter().map(|&old| written[old].clone()).collect();
assert_contents(&mapped, &expected);
assert_contents(&heap, &expected);
}
#[test]
fn mapped_data_pointer_is_aligned_for_f32_slices() {
let dir = tempdir().expect("tempdir");
let dimension = 3; let mut storage =
ContiguousVectors::new_file_backed(&dir.path().join("al.arena"), dimension, 16)
.expect("file arena");
fill(&mut storage, 40, dimension);
let addr = storage.as_flat_slice().as_ptr() as usize;
assert_eq!(
addr % std::mem::align_of::<f32>(),
0,
"data pointer {addr:#x} must satisfy from_raw_parts' alignment contract"
);
assert_eq!(
addr % DATA_OFFSET,
0,
"data region should start on the page boundary DATA_OFFSET promises"
);
}
#[test]
#[cfg(target_endian = "little")]
fn arena_bytes_are_the_raw_native_representation() {
let dir = tempdir().expect("tempdir");
let path = dir.path().join("e.arena");
let dimension = 2;
let mut storage = ContiguousVectors::new_file_backed(&path, dimension, 16).expect("file arena");
storage.push(&[1.5_f32, -2.25]).expect("push");
storage.flush_backing().expect("flush");
let raw = std::fs::read(&path).expect("read arena file");
let data = &raw[DATA_OFFSET..DATA_OFFSET + 8];
let mut expected = Vec::new();
expected.extend_from_slice(&1.5_f32.to_le_bytes());
expected.extend_from_slice(&(-2.25_f32).to_le_bytes());
assert_eq!(
data, expected,
"the data region is the f32 values themselves, unconverted"
);
}
#[test]
fn a_second_arena_over_the_same_file_is_refused() {
let dir = tempdir().expect("tempdir");
let path = dir.path().join("excl.arena");
let first = ContiguousVectors::new_file_backed(&path, 8, 16).expect("first arena");
let err = ContiguousVectors::new_file_backed(&path, 8, 16)
.expect_err("a second mapping of the same file must be refused");
assert!(
matches!(err, crate::error::Error::DatabaseLocked(ref p) if p.contains("excl.arena")),
"a refused lock should surface as DatabaseLocked naming the path, got: {err:?}"
);
drop(first);
drop(ContiguousVectors::new_file_backed(&path, 8, 16).expect("reopen after release"));
}
#[test]
fn a_refused_second_arena_leaves_the_first_intact() {
let dir = tempdir().expect("tempdir");
let path = dir.path().join("trunc.arena");
let dimension = 4;
let mut first = ContiguousVectors::new_file_backed(&path, dimension, 16).expect("first arena");
let written = fill(&mut first, 8, dimension);
let err = ContiguousVectors::new_file_backed(&path, dimension, 16)
.expect_err("a second mapping of the same file must be refused");
assert!(
matches!(err, crate::error::Error::DatabaseLocked(_)),
"expected a locked-resource error, got: {err:?}"
);
assert_contents(&first, &written);
}
#[test]
fn creating_over_an_existing_file_discards_its_contents() {
let dir = tempdir().expect("tempdir");
let path = dir.path().join("stale.arena");
let dimension = 4;
{
let mut old = ContiguousVectors::new_file_backed(&path, dimension, 64).expect("first");
fill(&mut old, 64, dimension);
old.flush_backing().expect("flush");
}
let mut fresh = ContiguousVectors::new_file_backed(&path, dimension, 16).expect("recreate");
fresh
.insert_at(8, &vector(dimension, 8))
.expect("insert_at");
for gap in [0_usize, 7] {
assert_eq!(
fresh.get(gap).expect("gap slot present"),
vec![0.0_f32; dimension].as_slice(),
"slot {gap} must be zeroed, not carried over from the old arena"
);
}
}
#[test]
fn evicting_preserves_every_vector() {
let dir = tempdir().expect("tempdir");
let path = dir.path().join("evict.arena");
let dimension = 128;
let count = 512;
let mut arena = ContiguousVectors::new_file_backed(&path, dimension, count).expect("create");
let written = fill(&mut arena, count, dimension);
arena.evict_backing().expect("eviction succeeds");
for (i, expected) in written.iter().enumerate() {
assert_eq!(
arena.get(i).expect("slot present"),
expected.as_slice(),
"vector {i} changed across an evict; the flush before MADV_DONTNEED is missing \
or ineffective, and a re-rank would score against wrong vectors"
);
}
}
#[test]
fn evicting_a_heap_arena_is_a_no_op() {
let dimension = 8;
let mut arena = ContiguousVectors::new(dimension, 16).expect("heap arena");
let written = fill(&mut arena, 16, dimension);
arena.evict_backing().expect("a heap arena reports success");
for (i, expected) in written.iter().enumerate() {
assert_eq!(arena.get(i).expect("slot present"), expected.as_slice());
}
}
#[test]
fn a_file_backed_arena_grows_by_an_eighth_and_a_heap_arena_doubles() {
let dir = tempdir().expect("tempdir");
let dimension = 4;
let mut mapped = ContiguousVectors::new_file_backed(&dir.path().join("e.arena"), dimension, 64)
.expect("file arena");
fill(&mut mapped, 65, dimension);
assert_eq!(
mapped.capacity(),
64 + 64 / 8,
"one past a full mapped arena grows it by an eighth"
);
let mut heap = ContiguousVectors::new(dimension, 64).expect("heap arena");
fill(&mut heap, 65, dimension);
assert_eq!(
heap.capacity(),
128,
"CONTROL: the heap arena still doubles"
);
}