mod common;
use tempfile::tempdir;
#[allow(unused_imports)]
use vyctor::storage::SearchResult;
use vyctor::storage::Storage;
fn create_test_storage(dimensions: usize) -> Option<Storage> {
if !common::vss_available() {
return None;
}
let dir = tempdir().expect("Failed to create temp directory");
let _db_path = dir.path().join("test.duckdb");
let dir = Box::leak(Box::new(dir));
Storage::new(&dir.path().join("test.duckdb"), dimensions).ok()
}
#[test]
fn test_storage_creation() {
if !common::vss_available() {
eprintln!("Skipping test: VSS extension not available");
return;
}
let dir = tempdir().unwrap();
let db_path = dir.path().join("test.duckdb");
let storage = Storage::new(&db_path, 64);
match storage {
Ok(_) => {
}
Err(e) => {
eprintln!("Skipping test: Storage creation failed: {}", e);
return;
}
}
}
#[test]
fn test_in_memory_storage() {
if !common::vss_available() {
eprintln!("Skipping test: VSS extension not available");
return;
}
let storage = Storage::in_memory(64);
match storage {
Ok(_) => {
}
Err(e) => {
eprintln!("Skipping test: In-memory storage creation failed: {}", e);
return;
}
}
}
#[test]
fn test_file_upsert_and_get() {
let storage = match create_test_storage(64) {
Some(s) => s,
None => {
eprintln!("Skipping test: VSS extension not available");
return;
}
};
let file_id = storage.upsert_file("src/main.rs", "hash123").unwrap();
assert!(file_id > 0);
let file = storage.get_file("src/main.rs").unwrap();
assert!(file.is_some());
let file = file.unwrap();
assert_eq!(file.path, "src/main.rs");
assert_eq!(file.content_hash, "hash123");
}
#[test]
fn test_file_update() {
let storage = match create_test_storage(64) {
Some(s) => s,
None => {
eprintln!("Skipping test: VSS extension not available");
return;
}
};
let id1 = storage.upsert_file("file.rs", "hash1").unwrap();
let id2 = storage.upsert_file("file.rs", "hash2").unwrap();
assert_eq!(id1, id2);
let file = storage.get_file("file.rs").unwrap().unwrap();
assert_eq!(file.content_hash, "hash2");
}
#[test]
fn test_file_delete() {
let storage = match create_test_storage(64) {
Some(s) => s,
None => {
eprintln!("Skipping test: VSS extension not available");
return;
}
};
storage.upsert_file("to_delete.rs", "hash").unwrap();
assert!(storage.get_file("to_delete.rs").unwrap().is_some());
let deleted = storage.delete_file("to_delete.rs").unwrap();
assert!(deleted);
assert!(storage.get_file("to_delete.rs").unwrap().is_none());
let deleted_again = storage.delete_file("to_delete.rs").unwrap();
assert!(!deleted_again);
}
#[test]
fn test_delete_multiple_files() {
let storage = match create_test_storage(64) {
Some(s) => s,
None => {
eprintln!("Skipping test: VSS extension not available");
return;
}
};
storage.upsert_file("file1.rs", "hash1").unwrap();
storage.upsert_file("file2.rs", "hash2").unwrap();
storage.upsert_file("file3.rs", "hash3").unwrap();
let paths = vec!["file1.rs".to_string(), "file3.rs".to_string()];
let deleted = storage.delete_files(&paths).unwrap();
assert_eq!(deleted, 2);
assert!(storage.get_file("file2.rs").unwrap().is_some());
assert!(storage.get_file("file1.rs").unwrap().is_none());
}
#[test]
fn test_get_all_file_paths() {
let storage = match create_test_storage(64) {
Some(s) => s,
None => {
eprintln!("Skipping test: VSS extension not available");
return;
}
};
storage.upsert_file("src/main.rs", "hash1").unwrap();
storage.upsert_file("src/lib.rs", "hash2").unwrap();
storage.upsert_file("tests/test.rs", "hash3").unwrap();
let paths = storage.get_all_file_paths().unwrap();
assert_eq!(paths.len(), 3);
assert!(paths.contains(&"src/main.rs".to_string()));
assert!(paths.contains(&"src/lib.rs".to_string()));
assert!(paths.contains(&"tests/test.rs".to_string()));
}
#[test]
fn test_chunk_insert() {
let storage = match create_test_storage(64) {
Some(s) => s,
None => {
eprintln!("Skipping test: VSS extension not available");
return;
}
};
let file_id = storage.upsert_file("test.rs", "hash").unwrap();
let embedding: Vec<f32> = (0..64).map(|i| i as f32 / 64.0).collect();
let chunk_id = storage
.insert_chunk(file_id, 0, "fn main() {}", 1, 3, &embedding)
.unwrap();
assert!(chunk_id > 0);
}
#[test]
fn test_chunk_batch_insert() {
let storage = match create_test_storage(64) {
Some(s) => s,
None => {
eprintln!("Skipping test: VSS extension not available");
return;
}
};
let file_id = storage.upsert_file("test.rs", "hash").unwrap();
let chunks: Vec<(i32, String, i32, i32, Vec<f32>)> = (0..5)
.map(|i| {
let embedding: Vec<f32> = (0..64).map(|j| (i * 64 + j) as f32 / 320.0).collect();
(i, format!("chunk {}", i), i * 10, (i + 1) * 10, embedding)
})
.collect();
storage.insert_chunks_batch(file_id, &chunks).unwrap();
let stats = storage.get_stats().unwrap();
assert_eq!(stats.chunk_count, 5);
}
#[test]
fn test_search() {
let storage = match create_test_storage(64) {
Some(s) => s,
None => {
eprintln!("Skipping test: VSS extension not available");
return;
}
};
let file_id = storage.upsert_file("test.rs", "hash").unwrap();
for i in 0..3 {
let embedding: Vec<f32> = (0..64).map(|j| if j == i { 1.0 } else { 0.0 }).collect();
storage
.insert_chunk(
file_id,
i as i32,
&format!("chunk content {}", i),
i as i32 * 10,
(i as i32 + 1) * 10,
&embedding,
)
.unwrap();
}
let query: Vec<f32> = (0..64).map(|j| if j == 0 { 1.0 } else { 0.0 }).collect();
let results = storage.search(&query, 3, None).unwrap();
assert!(!results.is_empty());
assert!(results[0].chunk_content.contains("chunk content"));
}
#[test]
fn test_search_with_folder_filter() {
let storage = match create_test_storage(64) {
Some(s) => s,
None => {
eprintln!("Skipping test: VSS extension not available");
return;
}
};
let file1_id = storage.upsert_file("src/main.rs", "hash1").unwrap();
let file2_id = storage.upsert_file("tests/test.rs", "hash2").unwrap();
let embedding: Vec<f32> = (0..64).map(|i| i as f32 / 64.0).collect();
storage
.insert_chunk(file1_id, 0, "main content", 1, 10, &embedding)
.unwrap();
storage
.insert_chunk(file2_id, 0, "test content", 1, 10, &embedding)
.unwrap();
let results = storage.search(&embedding, 10, Some("src/")).unwrap();
assert_eq!(results.len(), 1);
assert_eq!(results[0].file_path, "src/main.rs");
}
#[test]
fn test_stats_empty_database() {
let storage = match create_test_storage(64) {
Some(s) => s,
None => {
eprintln!("Skipping test: VSS extension not available");
return;
}
};
let stats = storage.get_stats().unwrap();
assert_eq!(stats.file_count, 0);
assert_eq!(stats.chunk_count, 0);
assert_eq!(stats.total_content_size, 0);
}
#[test]
fn test_stats_with_data() {
let storage = match create_test_storage(64) {
Some(s) => s,
None => {
eprintln!("Skipping test: VSS extension not available");
return;
}
};
let file_id = storage.upsert_file("test.rs", "hash").unwrap();
let embedding: Vec<f32> = vec![0.0; 64];
storage
.insert_chunk(file_id, 0, "hello world", 1, 1, &embedding)
.unwrap();
storage
.insert_chunk(file_id, 1, "goodbye", 2, 2, &embedding)
.unwrap();
let stats = storage.get_stats().unwrap();
assert_eq!(stats.file_count, 1);
assert_eq!(stats.chunk_count, 2);
assert_eq!(stats.total_content_size, 18); }
#[test]
fn test_clear() {
let storage = match create_test_storage(64) {
Some(s) => s,
None => {
eprintln!("Skipping test: VSS extension not available");
return;
}
};
let file_id = storage.upsert_file("test.rs", "hash").unwrap();
let embedding: Vec<f32> = vec![0.0; 64];
storage
.insert_chunk(file_id, 0, "content", 1, 1, &embedding)
.unwrap();
let stats = storage.get_stats().unwrap();
assert_eq!(stats.file_count, 1);
storage.clear().unwrap();
let stats = storage.get_stats().unwrap();
assert_eq!(stats.file_count, 0);
assert_eq!(stats.chunk_count, 0);
}
#[test]
fn test_file_update_clears_chunks() {
let storage = match create_test_storage(64) {
Some(s) => s,
None => {
eprintln!("Skipping test: VSS extension not available");
return;
}
};
let file_id = storage.upsert_file("test.rs", "hash1").unwrap();
let embedding: Vec<f32> = vec![0.0; 64];
storage
.insert_chunk(file_id, 0, "old content", 1, 1, &embedding)
.unwrap();
assert_eq!(storage.get_stats().unwrap().chunk_count, 1);
storage.upsert_file("test.rs", "hash2").unwrap();
assert_eq!(storage.get_stats().unwrap().chunk_count, 0);
}
#[test]
fn test_needs_rebuild() {
let storage = match create_test_storage(64) {
Some(s) => s,
None => {
eprintln!("Skipping test: VSS extension not available");
return;
}
};
assert!(!storage.needs_rebuild(128).unwrap());
let file_id = storage.upsert_file("test.rs", "hash").unwrap();
let embedding: Vec<f32> = vec![0.0; 64];
storage
.insert_chunk(file_id, 0, "content", 1, 1, &embedding)
.unwrap();
assert!(!storage.needs_rebuild(64).unwrap());
assert!(storage.needs_rebuild(128).unwrap());
}