use super::precision_contract_tests as suite;
use super::rabitq_precision::{RaBitQCodec, RaBitQPrecisionConfig};
use crate::distance::DistanceMetric;
fn binary_path_config() -> RaBitQPrecisionConfig {
RaBitQPrecisionConfig {
min_index_size: 0,
..RaBitQPrecisionConfig::default()
}
}
#[test]
fn test_rabitq_precision_empty_index() {
suite::check_empty_index::<RaBitQCodec>(64);
}
#[test]
fn test_rabitq_precision_fallback_when_untrained() {
suite::check_untrained_fallback::<RaBitQCodec>(32);
}
#[test]
fn test_rabitq_precision_insert_trains_lazily() {
suite::check_lazy_train_at_threshold::<RaBitQCodec>(64);
}
#[test]
fn test_rabitq_precision_force_train() {
suite::check_force_train::<RaBitQCodec>(64);
}
#[test]
fn test_rabitq_precision_search_after_training() {
suite::check_post_training_search_sorted::<RaBitQCodec>(64);
}
#[test]
fn test_rabitq_precision_insert_after_training() {
suite::check_insert_after_training_alignment::<RaBitQCodec>(32);
}
#[test]
fn test_rabitq_euclidean_returns_sqrt_not_squared() {
suite::check_euclidean_rerank_is_sqrt::<RaBitQCodec>(32);
}
#[test]
fn test_rabitq_below_min_index_size_falls_back_to_f32() {
suite::check_below_min_index_fallback::<RaBitQCodec>(32);
}
#[test]
fn test_rabitq_precision_recall_above_threshold() {
suite::check_recall_10k::<RaBitQCodec>();
}
#[cfg(feature = "persistence")]
fn train_rabitq(samples: &[Vec<f32>]) -> std::sync::Arc<crate::quantization::RaBitQIndex> {
std::sync::Arc::new(crate::quantization::RaBitQIndex::train(samples, 42).expect("train"))
}
#[cfg(feature = "persistence")]
#[test]
fn test_install_trained_rabitq_encodes_existing_vectors() {
suite::check_install_encodes_existing::<RaBitQCodec>(64, train_rabitq, 0.7);
}
#[cfg(feature = "persistence")]
#[test]
fn test_install_trained_rabitq_then_insert_keeps_alignment() {
suite::check_install_then_insert_alignment::<RaBitQCodec>(64, train_rabitq);
}
#[test]
fn test_rabitq_precision_config_default_min_index_size() {
assert_eq!(RaBitQPrecisionConfig::default().min_index_size, 5000);
}
fn run_rabitq_self_query(metric: DistanceMetric) {
let (dim, k) = (64, 10);
let (hnsw, vectors) = suite::trained_planted_backend::<RaBitQCodec>(metric, dim);
let query = &vectors[suite::PLANTED_QUERY_ID];
let results = hnsw.search_with_config(query, k, 100, &binary_path_config());
suite::assert_top1_and_recall(&results, &vectors, suite::PLANTED_QUERY_ID, metric, k);
}
#[test]
fn test_rabitq_cosine_rerank_keeps_best_candidates() {
run_rabitq_self_query(DistanceMetric::Cosine);
}
#[test]
fn test_rabitq_dot_product_rerank_keeps_best_candidates() {
run_rabitq_self_query(DistanceMetric::DotProduct);
}
#[test]
fn test_rabitq_cosine_unnormalized_query_matches_normalized() {
suite::check_cosine_scale_invariance::<RaBitQCodec>(64);
}
#[test]
fn test_rabitq_recall_survives_locality_reorder() {
suite::check_recall_survives_reorder::<RaBitQCodec>();
}