use alpha_id::packed::{corpus_sha256, read_packed, write_packed, PackedHeader}; use std::io::Write; use alpha_id::embed::EmbeddingStore; use alpha_id::model::AlphaIdEntry; use alpha_id::packed::{pack_from_store, packed_path, PackOutcome}; fn header(n_rows: u32, dim: u32) -> PackedHeader { PackedHeader { n_rows, dim, embed_model: "test/model".to_string(), corpus_sha256: "deadbeef".to_string(), corpus_name: "corpus.txt".to_string(), } } #[test] fn write_read_roundtrip_preserves_header_and_rows() { let dir = tempfile::tempdir().unwrap(); let path = dir.path().join("packed.bin"); let rows = vec![vec![0.0f32, 1.5, -2.25], vec![3.0, 4.0, 5.0]]; let h = header(2, 3); write_packed(&path, &h, &rows).unwrap(); let (got_h, got_rows) = read_packed(&path).unwrap(); assert_eq!(got_h, h); assert_eq!(got_rows, rows); } #[test] fn corpus_sha256_stable_and_sensitive() { let dir = tempfile::tempdir().unwrap(); let p = dir.path().join("c.txt"); std::fs::write(&p, b"alpha|beta").unwrap(); let a = corpus_sha256(p.to_str().unwrap()).unwrap(); let b = corpus_sha256(p.to_str().unwrap()).unwrap(); assert_eq!(a, b, "same bytes hash identically"); std::fs::write(&p, b"alpha|betb").unwrap(); let c = corpus_sha256(p.to_str().unwrap()).unwrap(); assert_ne!(a, c, "one changed byte changes the hash"); } #[test] fn read_packed_rejects_bad_magic() { let dir = tempfile::tempdir().unwrap(); let path = dir.path().join("bad.bin"); let mut f = std::fs::File::create(&path).unwrap(); f.write_all(b"XXXX____________").unwrap(); assert!(read_packed(&path).is_err()); } fn mk_entry(text: &str) -> AlphaIdEntry { AlphaIdEntry { alpha_id: "A0001".to_string(), valid: true, icd_primary: "A00".to_string(), icd_star: String::new(), icd_addon: String::new(), icd_primary2: String::new(), orpha: String::new(), text: text.to_string(), } } #[test] fn pack_from_store_complete_builds_header_and_writes_file() { let dir = tempfile::tempdir().unwrap(); let index_dir = dir.path().join("index"); std::fs::create_dir_all(&index_dir).unwrap(); let corpus = dir.path().join("corpus.txt"); std::fs::write(&corpus, b"corpus bytes").unwrap(); let store = EmbeddingStore::open(index_dir.to_str().unwrap(), "test/model").unwrap(); store.put("alpha", &[1.0f32, 0.0, 0.0]).unwrap(); store.put("beta", &[0.0f32, 1.0, 0.0]).unwrap(); let entries = vec![mk_entry("alpha"), mk_entry("beta")]; let outcome = pack_from_store( index_dir.to_str().unwrap(), "test/model", corpus.to_str().unwrap(), &entries, ) .unwrap(); match outcome { PackOutcome::Packed(h) => { assert_eq!(h.n_rows, 2); assert_eq!(h.dim, 3); assert_eq!(h.embed_model, "test/model"); assert_eq!( h.corpus_sha256, alpha_id::packed::corpus_sha256(corpus.to_str().unwrap()).unwrap() ); } PackOutcome::Incomplete { .. } => panic!("a complete store must pack"), } assert!(packed_path(index_dir.to_str().unwrap(), "test/model").exists()); } #[test] fn pack_from_store_incomplete_reports_counts_and_writes_nothing() { let dir = tempfile::tempdir().unwrap(); let index_dir = dir.path().join("index"); std::fs::create_dir_all(&index_dir).unwrap(); let corpus = dir.path().join("corpus.txt"); std::fs::write(&corpus, b"corpus bytes").unwrap(); let store = EmbeddingStore::open(index_dir.to_str().unwrap(), "test/model").unwrap(); store.put("alpha", &[1.0f32, 0.0]).unwrap(); // only 1 of 2 entries cached let entries = vec![mk_entry("alpha"), mk_entry("beta")]; let outcome = pack_from_store( index_dir.to_str().unwrap(), "test/model", corpus.to_str().unwrap(), &entries, ) .unwrap(); assert!(matches!(outcome, PackOutcome::Incomplete { cached: 1, total: 2 })); assert!( !packed_path(index_dir.to_str().unwrap(), "test/model").exists(), "an incomplete store must not write a packed file" ); }