use chaotic_semantic_memory::{
ConceptBuilder, FilterStrategy, HVec10240, MetadataFilter,
singularity::{Singularity, SingularityConfig},
};
use serde_json::json;
const NS: &str = "_default";
fn inject_concept(
sing: &mut Singularity,
id: &str,
metadata_key: &str,
metadata_val: serde_json::Value,
) {
let vector = HVec10240::random();
let concept = ConceptBuilder::new(id)
.with_vector(vector)
.with_metadata(metadata_key, metadata_val)
.build()
.unwrap();
sing.inject(NS, concept).unwrap();
}
#[test]
fn test_find_similar_filtered_returns_matching_only() {
let mut sing = Singularity::new(SingularityConfig::default());
inject_concept(&mut sing, "doc1", "category", json!("document"));
inject_concept(&mut sing, "doc2", "category", json!("document"));
inject_concept(&mut sing, "img1", "category", json!("image"));
let query = HVec10240::random();
let filter = MetadataFilter::eq("category", "document");
let results = sing.find_similar_filtered(NS, &query, 10, &filter);
for (id, _) in results.iter() {
let concept = sing.get(NS, id).unwrap();
assert_eq!(concept.metadata.get("category"), Some(&json!("document")));
}
}
#[test]
fn test_find_similar_filtered_empty_result() {
let mut sing = Singularity::new(SingularityConfig::default());
inject_concept(&mut sing, "doc1", "category", json!("document"));
let query = HVec10240::random();
let filter = MetadataFilter::eq("category", "video");
let results = sing.find_similar_filtered(NS, &query, 10, &filter);
assert!(results.is_empty());
}
#[test]
fn test_retrieval_stats_contains_selectivity_ratio() {
let mut sing = Singularity::new(SingularityConfig::default());
for i in 0..3 {
inject_concept(&mut sing, &format!("match{i}"), "type", json!("match"));
}
for i in 0..7 {
inject_concept(&mut sing, &format!("other{i}"), "type", json!("other"));
}
let query = HVec10240::random();
let filter = MetadataFilter::eq("type", "match");
let _ = sing.find_similar_filtered(NS, &query, 5, &filter);
let stats = sing.last_retrieval_stats(NS);
assert!((stats.selectivity_ratio - 0.3).abs() < 0.01);
}
#[test]
fn test_small_dataset_uses_pre_filter() {
let mut sing = Singularity::new(SingularityConfig::default());
for i in 0..5 {
inject_concept(&mut sing, &format!("c{i}"), "tag", json!(i % 2));
}
let query = HVec10240::random();
let filter = MetadataFilter::eq("tag", 1);
let _ = sing.find_similar_filtered(NS, &query, 3, &filter);
let stats = sing.last_retrieval_stats(NS);
assert_eq!(stats.filter_strategy, Some(FilterStrategy::Pre));
}
#[test]
fn test_low_selectivity_uses_pre_filter() {
let mut sing = Singularity::new(SingularityConfig::default());
for i in 0..3 {
inject_concept(&mut sing, &format!("match{i}"), "rare", json!("yes"));
}
for i in 0..22 {
inject_concept(&mut sing, &format!("common{i}"), "rare", json!("no"));
}
let query = HVec10240::random();
let filter = MetadataFilter::eq("rare", "yes");
let _ = sing.find_similar_filtered(NS, &query, 5, &filter);
let stats = sing.last_retrieval_stats(NS);
assert_eq!(stats.filter_strategy, Some(FilterStrategy::Pre));
}
#[test]
fn test_medium_selectivity_uses_bucket_post() {
let mut sing = Singularity::new(SingularityConfig::default());
for i in 0..10 {
inject_concept(&mut sing, &format!("match{i}"), "level", json!("high"));
}
for i in 0..15 {
inject_concept(&mut sing, &format!("low{i}"), "level", json!("low"));
}
let query = HVec10240::random();
let filter = MetadataFilter::eq("level", "high");
let _ = sing.find_similar_filtered(NS, &query, 5, &filter);
let stats = sing.last_retrieval_stats(NS);
assert_eq!(stats.filter_strategy, Some(FilterStrategy::BucketPost));
}
#[test]
fn test_high_selectivity_uses_scan_post() {
let mut sing = Singularity::new(SingularityConfig::default());
for i in 0..22 {
inject_concept(&mut sing, &format!("major{i}"), "group", json!("a"));
}
for i in 0..3 {
inject_concept(&mut sing, &format!("minor{i}"), "group", json!("b"));
}
let query = HVec10240::random();
let filter = MetadataFilter::eq("group", "a");
let _ = sing.find_similar_filtered(NS, &query, 5, &filter);
let stats = sing.last_retrieval_stats(NS);
assert_eq!(stats.filter_strategy, Some(FilterStrategy::ScanPost));
}
#[test]
fn test_complex_filter_with_nested_predicates() {
let mut sing = Singularity::new(SingularityConfig::default());
let c1 = ConceptBuilder::new("c1")
.with_vector(HVec10240::random())
.with_metadata("type", json!("doc"))
.with_metadata("public", json!(true))
.build()
.unwrap();
sing.inject(NS, c1).unwrap();
let c2 = ConceptBuilder::new("c2")
.with_vector(HVec10240::random())
.with_metadata("type", json!("doc"))
.with_metadata("public", json!(false))
.build()
.unwrap();
sing.inject(NS, c2).unwrap();
let c3 = ConceptBuilder::new("c3")
.with_vector(HVec10240::random())
.with_metadata("type", json!("img"))
.with_metadata("public", json!(true))
.build()
.unwrap();
sing.inject(NS, c3).unwrap();
let query = HVec10240::random();
let filter = MetadataFilter::and(vec![
MetadataFilter::eq("type", "doc"),
MetadataFilter::eq("public", true),
]);
let results = sing.find_similar_filtered(NS, &query, 10, &filter);
assert_eq!(results.len(), 1);
assert_eq!(results[0].0, "c1");
}
#[test]
fn test_find_similar_filtered_respects_top_k() {
let mut sing = Singularity::new(SingularityConfig::default());
for i in 0..10 {
inject_concept(&mut sing, &format!("doc{i}"), "type", json!("doc"));
}
let query = HVec10240::random();
let filter = MetadataFilter::eq("type", "doc");
let results = sing.find_similar_filtered(NS, &query, 3, &filter);
assert!(results.len() <= 3);
}