use super::Collection;
use crate::distance::DistanceMetric;
use crate::fusion::FusionStrategy;
use crate::point::Point;
use crate::velesql::FusionConfig;
use std::collections::HashMap;
use tempfile::TempDir;
fn config(strategy: &str, k: Option<f64>) -> FusionConfig {
let mut params = std::collections::HashMap::new();
if let Some(k) = k {
params.insert("k".to_string(), k);
}
FusionConfig {
strategy: strategy.to_string(),
params,
}
}
#[test]
fn maps_average_strategy() {
let strat = Collection::fused_config_to_strategy(&config("average", None));
assert_eq!(strat, FusionStrategy::Average);
}
#[test]
fn maps_maximum_strategy() {
let strat = Collection::fused_config_to_strategy(&config("maximum", None));
assert_eq!(strat, FusionStrategy::Maximum);
}
#[test]
fn maps_rrf_strategy_with_default_k() {
let strat = Collection::fused_config_to_strategy(&config("rrf", None));
assert_eq!(strat, FusionStrategy::RRF { k: 60 });
}
#[test]
fn rrf_honors_explicit_k() {
let strat = Collection::fused_config_to_strategy(&config("rrf", Some(42.0)));
assert_eq!(strat, FusionStrategy::RRF { k: 42 });
}
#[test]
fn unknown_strategy_falls_back_to_rrf() {
for name in ["weighted", "rsf", "nonsense"] {
let strat = Collection::fused_config_to_strategy(&config(name, Some(7.0)));
assert_eq!(
strat,
FusionStrategy::RRF { k: 7 },
"strategy '{name}' must fall back to RRF (honoring k)"
);
}
}
#[test]
fn strategy_name_is_case_insensitive() {
assert_eq!(
Collection::fused_config_to_strategy(&config("AVERAGE", None)),
FusionStrategy::Average
);
assert_eq!(
Collection::fused_config_to_strategy(&config("Maximum", None)),
FusionStrategy::Maximum
);
}
#[test]
fn a_near_fused_query_returns_the_fused_hits_best_first() {
let dir = TempDir::new().expect("test: temp dir");
let col = Collection::create(dir.path().join("fused"), 2, DistanceMetric::Cosine)
.expect("test: create collection");
let point = |id: u64, vector: [f32; 2]| Point {
id,
vector: vector.to_vec(),
payload: Some(serde_json::json!({ "id": id })),
sparse_vectors: None,
};
col.upsert(vec![
point(10, [1.0, 0.0]),
point(20, [0.0, 1.0]),
point(30, [1.0, 1.0]),
point(40, [-1.0, 0.0]),
])
.expect("test: upsert");
let params = HashMap::from([
("a".to_string(), serde_json::json!([1.0, 0.0])),
("b".to_string(), serde_json::json!([0.5, 1.0])),
]);
let results = col
.execute_query_str(
"SELECT * FROM docs WHERE vector NEAR_FUSED [$a, $b] LIMIT 4",
¶ms,
)
.expect("test: the fused query runs");
let ids: Vec<u64> = results.iter().map(|r| r.point.id).collect();
assert_eq!(ids, [30, 10, 20, 40]);
}