#![cfg(feature = "integration")]
use embeddenator_fs::EmbrFS;
use embeddenator_io::{read_bincode_file, read_json_file, write_bincode_file, write_json_file};
use embeddenator_retrieval::{BruteForceIndex, IndexConfig, RetrievalIndex};
use embeddenator_vsa::{ReversibleVSAConfig, SparseVec};
use serde::{Deserialize, Serialize};
use std::fs;
use tempfile::tempdir;
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
struct Document {
id: String,
content: String,
}
#[test]
fn test_ingest_query_extract_workflow() {
let dir = tempdir().unwrap();
let source_dir = dir.path().join("source");
let extract_dir = dir.path().join("extracted");
fs::create_dir_all(&source_dir).unwrap();
fs::write(source_dir.join("doc1.txt"), b"This is document one").unwrap();
fs::write(source_dir.join("doc2.txt"), b"This is document two").unwrap();
fs::write(source_dir.join("doc3.txt"), b"This is document three").unwrap();
let config = ReversibleVSAConfig::default();
let mut embrfs = EmbrFS::new();
embrfs
.ingest_directory(&source_dir, false, &config)
.unwrap();
EmbrFS::extract(
&embrfs.engram,
&embrfs.manifest,
&extract_dir,
false,
&config,
)
.unwrap();
let extracted1 = fs::read(extract_dir.join("doc1.txt")).unwrap();
let extracted2 = fs::read(extract_dir.join("doc2.txt")).unwrap();
let extracted3 = fs::read(extract_dir.join("doc3.txt")).unwrap();
assert_eq!(extracted1, b"This is document one");
assert_eq!(extracted2, b"This is document two");
assert_eq!(extracted3, b"This is document three");
}
#[test]
fn test_index_persistence_workflow() {
let dir = tempdir().unwrap();
let config = ReversibleVSAConfig::default();
let documents = vec![
Document {
id: "doc1".into(),
content: "Machine learning basics".into(),
},
Document {
id: "doc2".into(),
content: "Deep learning neural networks".into(),
},
Document {
id: "doc3".into(),
content: "Statistical analysis methods".into(),
},
Document {
id: "doc4".into(),
content: "Data preprocessing techniques".into(),
},
];
let vectors: Vec<(String, SparseVec)> = documents
.iter()
.map(|doc| {
let vec = SparseVec::encode_data(doc.content.as_bytes(), &config, None);
(doc.id.clone(), vec)
})
.collect();
let vectors_path = dir.path().join("vectors.bin");
let docs_path = dir.path().join("documents.json");
write_bincode_file(&vectors_path, &vectors).unwrap();
write_json_file(&docs_path, &documents).unwrap();
let loaded_vectors: Vec<(String, SparseVec)> = read_bincode_file(&vectors_path).unwrap();
let loaded_docs: Vec<Document> = read_json_file(&docs_path).unwrap();
assert_eq!(loaded_vectors.len(), 4);
assert_eq!(loaded_docs.len(), 4);
let mut index = BruteForceIndex::new(IndexConfig::default());
for (i, (_id, vec)) in loaded_vectors.iter().enumerate() {
index.add(i, vec);
}
index.finalize();
let query = SparseVec::encode_data(b"Deep learning neural networks", &config, None);
let results = index.query_top_k(&query, 2);
assert!(!results.is_empty());
assert_eq!(results[0].id, 1, "Exact match should be found");
}
#[test]
fn test_multi_format_workflow() {
let dir = tempdir().unwrap();
let config = ReversibleVSAConfig::default();
let vec = SparseVec::encode_data(b"test content", &config, None);
let bin_path = dir.path().join("data.bin");
let json_path = dir.path().join("data.json");
write_bincode_file(&bin_path, &vec).unwrap();
write_json_file(&json_path, &vec).unwrap();
let from_bin: SparseVec = read_bincode_file(&bin_path).unwrap();
let from_json: SparseVec = read_json_file(&json_path).unwrap();
assert_eq!(vec.pos, from_bin.pos);
assert_eq!(vec.neg, from_bin.neg);
assert_eq!(vec.pos, from_json.pos);
assert_eq!(vec.neg, from_json.neg);
let vec2 = SparseVec::encode_data(b"other content", &config, None);
let cosine_orig = vec.cosine(&vec2);
let cosine_bin = from_bin.cosine(&vec2);
let cosine_json = from_json.cosine(&vec2);
assert!((cosine_orig - cosine_bin).abs() < 1e-10);
assert!((cosine_orig - cosine_json).abs() < 1e-10);
}
#[test]
fn test_batch_processing_workflow() {
let config = ReversibleVSAConfig::default();
let batch_size = 100;
let mut vectors = Vec::with_capacity(batch_size);
for i in 0..batch_size {
let content = format!("Document number {} with unique content {}", i, i * 17);
let vec = SparseVec::encode_data(content.as_bytes(), &config, None);
vectors.push(vec);
}
let mut index = BruteForceIndex::new(IndexConfig::default());
for (i, vec) in vectors.iter().enumerate() {
index.add(i, vec);
}
index.finalize();
let query_content = format!("Document number {} with unique content {}", 42, 42 * 17);
let query = SparseVec::encode_data(query_content.as_bytes(), &config, None);
let results = index.query_top_k(&query, 5);
assert!(!results.is_empty());
assert_eq!(results[0].id, 42, "Should find exact match as top result");
}