use ahash::AHashMap;
use std::collections::HashMap;
use terraphim_config::{Config, ConfigState, Haystack, Role, ServiceType};
use terraphim_persistence::Persistable;
use terraphim_service::TerraphimService;
use terraphim_types::{
Document, Layer, NormalizedTermValue, RelevanceFunction, RoleName, SearchQuery,
};
#[tokio::test]
async fn test_weighted_haystack_ranking() {
if std::env::var("RUN_WEIGHTED_HAYSTACK_TESTS")
.map(|v| v != "1" && !v.eq_ignore_ascii_case("true"))
.unwrap_or(true)
{
eprintln!(
"Skipping: set RUN_WEIGHTED_HAYSTACK_TESTS=1 to run weighted haystack ranking tests"
);
return;
}
let high_weight_doc = Document {
id: "high_weight_doc".to_string(),
url: "local/high_weight.md".to_string(),
title: "High Weight Document".to_string(),
body: "This document comes from a high-priority local haystack. It should rank higher."
.to_string(),
description: Some("High priority document".to_string()),
summarization: None,
stub: None,
tags: None,
rank: Some(10), source_haystack: Some("./local_docs".to_string()),
doc_type: terraphim_types::DocumentType::KgEntry,
synonyms: None,
route: None,
priority: None,
};
let low_weight_doc = Document {
id: "low_weight_doc".to_string(),
url: "remote/low_weight.md".to_string(),
title: "Low Weight Document".to_string(),
body: "This document comes from a low-priority remote haystack. It should rank lower."
.to_string(),
description: Some("Low priority document".to_string()),
summarization: None,
stub: None,
tags: None,
rank: Some(20), source_haystack: Some("https://remote.api".to_string()),
doc_type: terraphim_types::DocumentType::KgEntry,
synonyms: None,
route: None,
priority: None,
};
let high_weight_haystack = Haystack {
location: "./local_docs".to_string(),
service: ServiceType::Ripgrep,
read_only: true,
atomic_server_secret: None,
extra_parameters: HashMap::new(),
fetch_content: false,
};
let low_weight_haystack = Haystack {
location: "https://remote.api".to_string(),
service: ServiceType::QueryRs,
read_only: true,
atomic_server_secret: None,
extra_parameters: HashMap::new(),
fetch_content: false,
};
let mut roles = AHashMap::new();
let test_role = Role {
name: RoleName::from("Test Role"),
shortname: Some("test".to_string()),
relevance_function: RelevanceFunction::TitleScorer,
terraphim_it: false,
theme: "default".to_string(),
kg: None,
haystacks: vec![high_weight_haystack, low_weight_haystack],
extra: AHashMap::new(),
llm_router_enabled: false,
llm_router_config: None,
..Default::default()
};
roles.insert(RoleName::from("Test Role"), test_role);
let mut config = Config {
id: terraphim_config::ConfigId::Server,
global_shortcut: "Ctrl+X".to_string(),
roles,
default_role: RoleName::from("Test Role"),
selected_role: RoleName::from("Test Role"),
};
let config_state = ConfigState::new(&mut config)
.await
.expect("Failed to create config state");
let mut service = TerraphimService::new(config_state);
high_weight_doc
.save()
.await
.expect("Failed to save high weight doc");
low_weight_doc
.save()
.await
.expect("Failed to save low weight doc");
let search_query = SearchQuery {
search_term: NormalizedTermValue::from("document"),
search_terms: None,
operator: None,
skip: None,
limit: None,
role: Some(RoleName::from("Test Role")),
layer: Layer::default(),
include_pinned: false,
};
let search_result = service.search(&search_query).await.expect("Search failed");
assert_eq!(search_result.len(), 2);
let high_weight_result = search_result
.iter()
.find(|d| d.id == "high_weight_doc")
.expect("High weight document not found");
let low_weight_result = search_result
.iter()
.find(|d| d.id == "low_weight_doc")
.expect("Low weight document not found");
assert_eq!(high_weight_result.rank, Some(30));
assert_eq!(low_weight_result.rank, Some(10));
assert!(search_result[0].rank.unwrap() >= search_result[1].rank.unwrap());
assert_eq!(search_result[0].id, "high_weight_doc");
assert_eq!(search_result[1].id, "low_weight_doc");
println!(
"✅ Weighted ranking test passed: High-weight document (rank {}) ranks before low-weight document (rank {})",
search_result[0].rank.unwrap(),
search_result[1].rank.unwrap()
);
}
#[tokio::test]
async fn test_default_weight_handling() {
if std::env::var("RUN_WEIGHTED_HAYSTACK_TESTS")
.map(|v| v != "1" && !v.eq_ignore_ascii_case("true"))
.unwrap_or(true)
{
eprintln!(
"Skipping: set RUN_WEIGHTED_HAYSTACK_TESTS=1 to run weighted haystack ranking tests"
);
return;
}
let doc_without_source = Document {
id: "no_source_doc".to_string(),
url: "test.md".to_string(),
title: "Document Without Source".to_string(),
body: "This document has no source haystack".to_string(),
description: None,
summarization: None,
stub: None,
tags: None,
rank: Some(15),
source_haystack: None, doc_type: terraphim_types::DocumentType::KgEntry,
synonyms: None,
route: None,
priority: None,
};
let mut roles = AHashMap::new();
let test_role = Role {
name: RoleName::from("Test Role"),
shortname: Some("test".to_string()),
relevance_function: RelevanceFunction::TitleScorer,
terraphim_it: false,
theme: "default".to_string(),
kg: None,
haystacks: vec![Haystack {
location: "./docs".to_string(),
service: ServiceType::Ripgrep,
read_only: true,
atomic_server_secret: None,
extra_parameters: HashMap::new(),
fetch_content: false,
}],
extra: AHashMap::new(),
llm_router_enabled: false,
llm_router_config: None,
..Default::default()
};
roles.insert(RoleName::from("Test Role"), test_role);
let mut config = Config {
id: terraphim_config::ConfigId::Server,
global_shortcut: "Ctrl+X".to_string(),
roles,
default_role: RoleName::from("Test Role"),
selected_role: RoleName::from("Test Role"),
};
let config_state = ConfigState::new(&mut config)
.await
.expect("Failed to create config state");
let mut service = TerraphimService::new(config_state);
doc_without_source
.save()
.await
.expect("Failed to save document");
let search_query = SearchQuery {
search_term: NormalizedTermValue::from("document"),
search_terms: None,
operator: None,
skip: None,
limit: None,
role: Some(RoleName::from("Test Role")),
layer: Layer::default(),
include_pinned: false,
};
let search_result = service.search(&search_query).await.expect("Search failed");
assert_eq!(search_result.len(), 1);
assert_eq!(search_result[0].rank, Some(15));
println!(
"✅ Default weight handling test passed: Document without source maintained rank {}",
search_result[0].rank.unwrap()
);
}