use std::fs;
use std::path::{Path, PathBuf};
use microscope_memory::config::Config;
fn build_index(root: &Path) -> Config {
let layers = root.join("layers");
fs::create_dir_all(&layers).unwrap();
fs::write(
layers.join("long_term.txt"),
"Microscope Memory uses hierarchical indexing.\n\n\
Memory management in Rust uses ownership and borrowing.\n\n\
A third statement, long enough to survive the text floor.\n",
)
.unwrap();
let mut config = Config::default();
config.paths.layers_dir = layers.to_string_lossy().to_string();
config.paths.output_dir = root.join("data").to_string_lossy().to_string();
config.paths.temp_dir = root.join("tmp").to_string_lossy().to_string();
config.memory_layers.layers = vec!["long_term".to_string()];
config.embedding.provider = "mock".to_string();
microscope_memory::build::build(&config, true, true).unwrap();
config
}
fn truncate(path: &Path, keep: usize) {
let data = fs::read(path).unwrap();
assert!(data.len() > keep, "file is already shorter than {keep}");
fs::write(path, &data[..keep]).unwrap();
}
#[test]
fn headers_shorter_than_the_claimed_block_count_are_refused() {
let tmp = tempfile::tempdir().unwrap();
let config = build_index(tmp.path());
let out = PathBuf::from(&config.paths.output_dir);
let headers = out.join("microscope.bin");
let original = fs::metadata(&headers).unwrap().len();
assert!(original > 0, "build produced no headers");
truncate(&headers, 50);
let err = microscope_memory::reader::MicroscopeReader::open(&config);
assert!(
err.is_err(),
"microscope.bin truncated from {original} to 50 bytes while meta.bin still \
claims the full count: open() accepted it, so header_unchecked can read \
past the mapping"
);
}
#[test]
fn empty_header_file_is_refused() {
let tmp = tempfile::tempdir().unwrap();
let config = build_index(tmp.path());
let out = PathBuf::from(&config.paths.output_dir);
fs::write(out.join("microscope.bin"), b"").unwrap();
assert!(
microscope_memory::reader::MicroscopeReader::open(&config).is_err(),
"an empty microscope.bin was accepted alongside a meta.bin claiming blocks"
);
}
#[test]
fn truncated_meta_is_refused() {
let tmp = tempfile::tempdir().unwrap();
let config = build_index(tmp.path());
let out = PathBuf::from(&config.paths.output_dir);
let meta = out.join("meta.bin");
truncate(&meta, 16);
assert!(
microscope_memory::reader::MicroscopeReader::open(&config).is_err(),
"meta.bin truncated mid depth-table was accepted"
);
}
#[test]
fn meta_with_a_foreign_magic_is_refused() {
let tmp = tempfile::tempdir().unwrap();
let config = build_index(tmp.path());
let out = PathBuf::from(&config.paths.output_dir);
let meta = out.join("meta.bin");
let mut data = fs::read(&meta).unwrap();
data[0..4].copy_from_slice(b"NOPE");
fs::write(&meta, &data).unwrap();
assert!(
microscope_memory::reader::MicroscopeReader::open(&config).is_err(),
"meta.bin with an unknown magic was accepted"
);
}