use tokensave::context::*;
use tokensave::types::*;
#[tokio::test]
async fn test_reranking_demotes_fixture_nodes() {
use tempfile::TempDir;
use tokensave::context::ContextBuilder;
use tokensave::db::Database;
let dir = TempDir::new().unwrap();
let project = dir.path();
let (db, _) = Database::initialize(&project.join(".tokensave/tokensave.db"))
.await
.unwrap();
let fixture_node = Node {
id: "enum_variant:fixture_debug".to_string(),
kind: NodeKind::EnumVariant,
name: "debug".to_string(),
qualified_name: "tests/fixtures/sample.dart::LogLevel::debug".to_string(),
file_path: "tests/fixtures/sample.dart".to_string(),
start_line: 14,
attrs_start_line: 14,
end_line: 14,
start_column: 0,
end_column: 10,
signature: Some("debug".to_string()),
docstring: None,
visibility: Visibility::Pub,
is_async: false,
branches: 0,
loops: 0,
returns: 0,
max_nesting: 0,
unsafe_blocks: 0,
unchecked_calls: 0,
assertions: 0,
cognitive_complexity: 0,
distinct_operators: 0,
distinct_operands: 0,
total_operators: 0,
total_operands: 0,
updated_at: 0,
parent_id: None,
};
db.insert_node(&fixture_node).await.unwrap();
let source_node = Node {
id: "function:debug_handler".to_string(),
kind: NodeKind::Function,
name: "debug_handler".to_string(),
qualified_name: "src/debug.rs::debug_handler".to_string(),
file_path: "src/debug.rs".to_string(),
start_line: 1,
attrs_start_line: 1,
end_line: 10,
start_column: 0,
end_column: 1,
signature: Some("pub fn debug_handler()".to_string()),
docstring: None,
visibility: Visibility::Pub,
is_async: false,
branches: 0,
loops: 0,
returns: 0,
max_nesting: 0,
unsafe_blocks: 0,
unchecked_calls: 0,
assertions: 0,
cognitive_complexity: 0,
distinct_operators: 0,
distinct_operands: 0,
total_operators: 0,
total_operands: 0,
updated_at: 0,
parent_id: None,
};
db.insert_node(&source_node).await.unwrap();
let builder = ContextBuilder::new(&db, project);
let result = builder
.build_context("debug", &BuildContextOptions::default())
.await
.unwrap();
assert!(!result.entry_points.is_empty());
assert_eq!(
result.entry_points[0].id, "function:debug_handler",
"source function should outrank fixture enum variant after re-ranking"
);
}
#[test]
fn test_extract_symbols_from_query() {
let symbols = extract_symbols_from_query("fix the process_request function");
assert!(symbols.contains(&"process_request".to_string()));
}
#[test]
fn test_extract_camel_case_symbols() {
let symbols = extract_symbols_from_query("update UserService handler");
assert!(symbols.contains(&"UserService".to_string()));
}
#[test]
fn test_extract_qualified_symbols() {
let symbols = extract_symbols_from_query("look at crate::types::Node");
assert!(symbols.iter().any(|s| s.contains("Node")));
}
#[test]
fn test_extract_screaming_snake_symbols() {
let symbols = extract_symbols_from_query("increase MAX_RETRIES");
assert!(symbols.contains(&"MAX_RETRIES".to_string()));
}
#[test]
fn test_extract_no_symbols_from_plain_english() {
let symbols = extract_symbols_from_query("the is in for to a an");
assert!(symbols.is_empty());
}
#[test]
fn test_format_context_markdown() {
let context = TaskContext {
query: "test query".to_string(),
summary: "Test summary".to_string(),
subgraph: Subgraph::default(),
entry_points: vec![],
code_blocks: vec![],
related_files: vec![],
seen_node_ids: vec![],
};
let md = format_context_as_markdown(&context);
assert!(md.contains("## Code Context"));
assert!(md.contains("test query"));
}
#[test]
fn test_format_context_json() {
let context = TaskContext {
query: "test".to_string(),
summary: "Summary".to_string(),
subgraph: Subgraph::default(),
entry_points: vec![],
code_blocks: vec![],
related_files: vec![],
seen_node_ids: vec![],
};
let json = format_context_as_json(&context);
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed["query"], "test");
}
#[tokio::test]
async fn test_build_context_with_db() {
use std::fs;
use tempfile::TempDir;
use tokensave::context::ContextBuilder;
use tokensave::db::Database;
let dir = TempDir::new().unwrap();
let project = dir.path();
fs::create_dir_all(project.join("src")).unwrap();
fs::write(project.join("src/lib.rs"), "pub fn process_data() {}\n").unwrap();
let (db, _) = Database::initialize(&project.join(".tokensave/tokensave.db"))
.await
.unwrap();
let node = Node {
id: "function:test123".to_string(),
kind: NodeKind::Function,
name: "process_data".to_string(),
qualified_name: "src/lib.rs::process_data".to_string(),
file_path: "src/lib.rs".to_string(),
start_line: 1,
attrs_start_line: 1,
end_line: 1,
start_column: 0,
end_column: 24,
signature: Some("pub fn process_data()".to_string()),
docstring: None,
visibility: Visibility::Pub,
is_async: false,
branches: 0,
loops: 0,
returns: 0,
max_nesting: 0,
unsafe_blocks: 0,
unchecked_calls: 0,
assertions: 0,
cognitive_complexity: 0,
distinct_operators: 0,
distinct_operands: 0,
total_operators: 0,
total_operands: 0,
updated_at: 0,
parent_id: None,
};
db.insert_node(&node).await.unwrap();
let builder = ContextBuilder::new(&db, project);
let result = builder
.build_context("process_data", &BuildContextOptions::default())
.await;
assert!(result.is_ok());
let ctx = result.unwrap();
assert!(!ctx.entry_points.is_empty());
}
#[tokio::test]
async fn test_get_code_reads_source_file() {
use std::fs;
use tempfile::TempDir;
use tokensave::context::ContextBuilder;
use tokensave::db::Database;
let dir = TempDir::new().unwrap();
let project = dir.path();
fs::create_dir_all(project.join("src")).unwrap();
fs::write(
project.join("src/main.rs"),
"fn main() {\n println!(\"hello\");\n}\n",
)
.unwrap();
let (db, _) = Database::initialize(&project.join(".tokensave/tokensave.db"))
.await
.unwrap();
let node = Node {
id: "function:main123".to_string(),
kind: NodeKind::Function,
name: "main".to_string(),
qualified_name: "src/main.rs::main".to_string(),
file_path: "src/main.rs".to_string(),
start_line: 0,
attrs_start_line: 0,
end_line: 2,
start_column: 0,
end_column: 1,
signature: Some("fn main()".to_string()),
docstring: None,
visibility: Visibility::Private,
is_async: false,
branches: 0,
loops: 0,
returns: 0,
max_nesting: 0,
unsafe_blocks: 0,
unchecked_calls: 0,
assertions: 0,
cognitive_complexity: 0,
distinct_operators: 0,
distinct_operands: 0,
total_operators: 0,
total_operands: 0,
updated_at: 0,
parent_id: None,
};
let builder = ContextBuilder::new(&db, project);
let code = builder.get_code(&node).unwrap();
assert!(code.is_some());
let content = code.unwrap();
assert!(content.contains("fn main()"));
assert!(content.contains("println!"));
}
#[tokio::test]
async fn test_get_code_returns_none_for_missing_file() {
use tempfile::TempDir;
use tokensave::context::ContextBuilder;
use tokensave::db::Database;
let dir = TempDir::new().unwrap();
let project = dir.path();
let (db, _) = Database::initialize(&project.join(".tokensave/tokensave.db"))
.await
.unwrap();
let node = Node {
id: "function:missing".to_string(),
kind: NodeKind::Function,
name: "missing".to_string(),
qualified_name: "nonexistent.rs::missing".to_string(),
file_path: "nonexistent.rs".to_string(),
start_line: 1,
attrs_start_line: 1,
end_line: 1,
start_column: 0,
end_column: 10,
signature: None,
docstring: None,
visibility: Visibility::Private,
is_async: false,
branches: 0,
loops: 0,
returns: 0,
max_nesting: 0,
unsafe_blocks: 0,
unchecked_calls: 0,
assertions: 0,
cognitive_complexity: 0,
distinct_operators: 0,
distinct_operands: 0,
total_operators: 0,
total_operands: 0,
updated_at: 0,
parent_id: None,
};
let builder = ContextBuilder::new(&db, project);
let code = builder.get_code(&node).unwrap();
assert!(code.is_none());
}
#[tokio::test]
async fn test_find_relevant_context() {
use tempfile::TempDir;
use tokensave::context::ContextBuilder;
use tokensave::db::Database;
let dir = TempDir::new().unwrap();
let project = dir.path();
let (db, _) = Database::initialize(&project.join(".tokensave/tokensave.db"))
.await
.unwrap();
let node = Node {
id: "function:ctx_test".to_string(),
kind: NodeKind::Function,
name: "compute".to_string(),
qualified_name: "src/lib.rs::compute".to_string(),
file_path: "src/lib.rs".to_string(),
start_line: 1,
attrs_start_line: 1,
end_line: 5,
start_column: 0,
end_column: 1,
signature: Some("pub fn compute()".to_string()),
docstring: None,
visibility: Visibility::Pub,
is_async: false,
branches: 0,
loops: 0,
returns: 0,
max_nesting: 0,
unsafe_blocks: 0,
unchecked_calls: 0,
assertions: 0,
cognitive_complexity: 0,
distinct_operators: 0,
distinct_operands: 0,
total_operators: 0,
total_operands: 0,
updated_at: 0,
parent_id: None,
};
db.insert_node(&node).await.unwrap();
let builder = ContextBuilder::new(&db, project);
let subgraph = builder
.find_relevant_context("compute", &BuildContextOptions::default())
.await
.unwrap();
assert!(!subgraph.nodes.is_empty());
}
#[tokio::test]
async fn test_exclude_node_ids_deduplication() {
use tempfile::TempDir;
use tokensave::context::ContextBuilder;
use tokensave::db::Database;
let dir = TempDir::new().unwrap();
let project = dir.path();
let (db, _) = Database::initialize(&project.join(".tokensave/tokensave.db"))
.await
.unwrap();
for (id, name) in [("fn:first", "compute"), ("fn:second", "compute_batch")] {
db.insert_node(&Node {
id: id.to_string(),
kind: NodeKind::Function,
name: name.to_string(),
qualified_name: format!("src/lib.rs::{name}"),
file_path: "src/lib.rs".to_string(),
start_line: 1,
attrs_start_line: 1,
end_line: 5,
start_column: 0,
end_column: 1,
signature: Some(format!("pub fn {name}()")),
docstring: None,
visibility: Visibility::Pub,
is_async: false,
branches: 0,
loops: 0,
returns: 0,
max_nesting: 0,
unsafe_blocks: 0,
unchecked_calls: 0,
assertions: 0,
cognitive_complexity: 0,
distinct_operators: 0,
distinct_operands: 0,
total_operators: 0,
total_operands: 0,
updated_at: 0,
parent_id: None,
})
.await
.unwrap();
}
let builder = ContextBuilder::new(&db, project);
let opts = BuildContextOptions::default();
let ctx1 = builder.build_context("compute", &opts).await.unwrap();
assert!(ctx1.entry_points.iter().any(|n| n.id == "fn:first"));
let opts2 = BuildContextOptions {
exclude_node_ids: vec!["fn:first".to_string()].into_iter().collect(),
..Default::default()
};
let ctx2 = builder.build_context("compute", &opts2).await.unwrap();
assert!(
!ctx2.entry_points.iter().any(|n| n.id == "fn:first"),
"excluded node should not appear in second call"
);
}
#[tokio::test]
async fn test_exact_name_match_wins_max_merge() {
use tempfile::TempDir;
use tokensave::context::ContextBuilder;
use tokensave::db::Database;
let dir = TempDir::new().unwrap();
let project = dir.path();
let (db, _) = Database::initialize(&project.join(".tokensave/tokensave.db"))
.await
.unwrap();
db.insert_node(&Node {
id: "variant:validate".to_string(),
kind: NodeKind::EnumVariant,
name: "validateInput".to_string(),
qualified_name: "src/lib.rs::Action::validateInput".to_string(),
file_path: "src/lib.rs".to_string(),
start_line: 1,
attrs_start_line: 1,
end_line: 1,
start_column: 0,
end_column: 10,
signature: Some("validateInput".to_string()),
docstring: None,
visibility: Visibility::Private,
is_async: false,
branches: 0,
loops: 0,
returns: 0,
max_nesting: 0,
unsafe_blocks: 0,
unchecked_calls: 0,
assertions: 0,
cognitive_complexity: 0,
distinct_operators: 0,
distinct_operands: 0,
total_operators: 0,
total_operands: 0,
updated_at: 0,
parent_id: None,
})
.await
.unwrap();
db.insert_node(&Node {
id: "fn:validate_helper".to_string(),
kind: NodeKind::Function,
name: "validateRequest".to_string(),
qualified_name: "src/lib.rs::validateRequest".to_string(),
file_path: "src/lib.rs".to_string(),
start_line: 2,
attrs_start_line: 2,
end_line: 6,
start_column: 0,
end_column: 1,
signature: Some("pub fn validateRequest()".to_string()),
docstring: None,
visibility: Visibility::Pub,
is_async: false,
branches: 0,
loops: 0,
returns: 0,
max_nesting: 0,
unsafe_blocks: 0,
unchecked_calls: 0,
assertions: 0,
cognitive_complexity: 0,
distinct_operators: 0,
distinct_operands: 0,
total_operators: 0,
total_operands: 0,
updated_at: 0,
parent_id: None,
})
.await
.unwrap();
let builder = ContextBuilder::new(&db, project);
let ctx = builder
.build_context("validateInput", &BuildContextOptions::default())
.await
.unwrap();
assert_eq!(
ctx.entry_points.first().map(|n| n.id.as_str()),
Some("variant:validate"),
"exact-name match should rank first via MAX-merge, not be buried by BM25"
);
let opts_excl = BuildContextOptions {
exclude_node_ids: vec!["variant:validate".to_string()].into_iter().collect(),
..Default::default()
};
let ctx_excl = builder
.build_context("validateInput", &opts_excl)
.await
.unwrap();
assert!(
!ctx_excl
.entry_points
.iter()
.any(|n| n.id == "variant:validate"),
"excluded node must not reappear via the exact-name supplement"
);
}
#[tokio::test]
async fn test_query_ignore_filters_context_entry_points() {
use tempfile::TempDir;
use tokensave::config::{load_query_ignore, QueryIgnore};
use tokensave::context::ContextBuilder;
use tokensave::db::Database;
let dir = TempDir::new().unwrap();
let project = dir.path();
let (db, _) = Database::initialize(&project.join(".tokensave/tokensave.db"))
.await
.unwrap();
for (id, file) in [
("fn:src", "src/widget.rs"),
("fn:gen", "generated/widget.rs"),
] {
db.insert_node(&Node {
id: id.to_string(),
kind: NodeKind::Function,
name: "widget".to_string(),
qualified_name: format!("{file}::widget"),
file_path: file.to_string(),
start_line: 1,
attrs_start_line: 1,
end_line: 5,
start_column: 0,
end_column: 1,
signature: Some("pub fn widget()".to_string()),
docstring: None,
visibility: Visibility::Pub,
is_async: false,
branches: 0,
loops: 0,
returns: 0,
max_nesting: 0,
unsafe_blocks: 0,
unchecked_calls: 0,
assertions: 0,
cognitive_complexity: 0,
distinct_operators: 0,
distinct_operands: 0,
total_operators: 0,
total_operands: 0,
updated_at: 0,
parent_id: None,
})
.await
.unwrap();
}
let builder = ContextBuilder::new(&db, project);
let opts = BuildContextOptions::default();
let ctx = builder.build_context("widget", &opts).await.unwrap();
assert!(ctx.entry_points.iter().any(|n| n.id == "fn:gen"));
let ts_dir = project.join(".tokensave");
std::fs::write(ts_dir.join("queryignore"), "generated\n").unwrap();
let query_ignore = load_query_ignore(project);
assert!(!query_ignore.is_empty());
let opts_ignored = BuildContextOptions {
query_ignore,
..Default::default()
};
let ctx_ignored = builder
.build_context("widget", &opts_ignored)
.await
.unwrap();
assert!(
!ctx_ignored.entry_points.iter().any(|n| n.id == "fn:gen"),
"queryignore-matched node should not appear as an entry point"
);
assert!(
ctx_ignored.entry_points.iter().any(|n| n.id == "fn:src"),
"non-matching node should still appear"
);
assert!(!QueryIgnore::default().is_ignored("generated/widget.rs"));
}
#[tokio::test]
async fn test_merge_adjacent_code_blocks() {
use std::fs;
use tempfile::TempDir;
use tokensave::context::ContextBuilder;
use tokensave::db::Database;
let dir = TempDir::new().unwrap();
let project = dir.path();
fs::create_dir_all(project.join("src")).unwrap();
fs::write(
project.join("src/lib.rs"),
"fn alpha() {}\n\nfn beta() {}\n\nfn gamma() {}\n",
)
.unwrap();
let (db, _) = Database::initialize(&project.join(".tokensave/tokensave.db"))
.await
.unwrap();
db.insert_node(&Node {
id: "fn:alpha".to_string(),
kind: NodeKind::Function,
name: "alpha".to_string(),
qualified_name: "src/lib.rs::alpha".to_string(),
file_path: "src/lib.rs".to_string(),
start_line: 0,
attrs_start_line: 0,
end_line: 0,
start_column: 0,
end_column: 13,
signature: Some("fn alpha()".to_string()),
docstring: None,
visibility: Visibility::Pub,
is_async: false,
branches: 0,
loops: 0,
returns: 0,
max_nesting: 0,
unsafe_blocks: 0,
unchecked_calls: 0,
assertions: 0,
cognitive_complexity: 0,
distinct_operators: 0,
distinct_operands: 0,
total_operators: 0,
total_operands: 0,
updated_at: 0,
parent_id: None,
})
.await
.unwrap();
db.insert_node(&Node {
id: "fn:beta".to_string(),
kind: NodeKind::Function,
name: "beta".to_string(),
qualified_name: "src/lib.rs::beta".to_string(),
file_path: "src/lib.rs".to_string(),
start_line: 2,
attrs_start_line: 2,
end_line: 2,
start_column: 0,
end_column: 12,
signature: Some("fn beta()".to_string()),
docstring: None,
visibility: Visibility::Pub,
is_async: false,
branches: 0,
loops: 0,
returns: 0,
max_nesting: 0,
unsafe_blocks: 0,
unchecked_calls: 0,
assertions: 0,
cognitive_complexity: 0,
distinct_operators: 0,
distinct_operands: 0,
total_operators: 0,
total_operands: 0,
updated_at: 0,
parent_id: None,
})
.await
.unwrap();
let builder = ContextBuilder::new(&db, project);
let ctx = builder
.build_context(
"alpha beta",
&BuildContextOptions {
include_code: true,
merge_adjacent: true,
max_code_blocks: 10,
..Default::default()
},
)
.await
.unwrap();
assert_eq!(
ctx.code_blocks.len(),
1,
"adjacent blocks should merge into one, got {}",
ctx.code_blocks.len()
);
assert!(ctx.code_blocks[0].content.contains("alpha"));
assert!(ctx.code_blocks[0].content.contains("beta"));
}
#[tokio::test]
async fn test_entry_points_capped_to_search_limit() {
use std::fs;
use tempfile::TempDir;
use tokensave::context::ContextBuilder;
use tokensave::db::Database;
let dir = TempDir::new().unwrap();
let project = dir.path();
fs::create_dir_all(project.join("src")).unwrap();
let (db, _) = Database::initialize(&project.join(".tokensave/tokensave.db"))
.await
.unwrap();
const NUM_NODES: usize = 12;
let keywords: Vec<String> = (0..NUM_NODES).map(|i| format!("widgetkind{i}")).collect();
let mut nodes = Vec::new();
for (i, kw) in keywords.iter().enumerate() {
nodes.push(Node {
id: format!("function:{kw}"),
kind: NodeKind::Function,
name: kw.clone(),
qualified_name: format!("src/file{i}.rs::{kw}"),
file_path: format!("src/file{i}.rs"),
start_line: 1,
attrs_start_line: 1,
end_line: 5,
start_column: 0,
end_column: 1,
signature: Some(format!("pub fn {kw}()")),
docstring: None,
visibility: Visibility::Pub,
is_async: false,
branches: 0,
loops: 0,
returns: 0,
max_nesting: 0,
unsafe_blocks: 0,
unchecked_calls: 0,
assertions: 0,
cognitive_complexity: 0,
distinct_operators: 0,
distinct_operands: 0,
total_operators: 0,
total_operands: 0,
updated_at: 0,
parent_id: None,
});
}
db.insert_nodes(&nodes).await.unwrap();
const SEARCH_LIMIT: usize = 5;
let opts = BuildContextOptions {
search_limit: SEARCH_LIMIT,
max_nodes: 100, max_per_file: Some(100),
extra_keywords: keywords.clone(),
..Default::default()
};
let builder = ContextBuilder::new(&db, project);
let ctx = builder.build_context(&keywords[0], &opts).await.unwrap();
assert!(
ctx.entry_points.len() > 1,
"expected multiple matching candidates, got {}",
ctx.entry_points.len()
);
assert!(
ctx.entry_points.len() <= SEARCH_LIMIT,
"entry points (BFS roots) must be capped to search_limit ({}), got {}",
SEARCH_LIMIT,
ctx.entry_points.len()
);
}
#[tokio::test]
async fn exact_qualified_expression_seeds_every_enclosing_symbol() {
use std::collections::HashSet;
use std::fs;
use tempfile::TempDir;
use tokensave::context::ContextBuilder;
use tokensave::tokensave::TokenSave;
let dir = TempDir::new().unwrap();
let project = dir.path();
fs::create_dir_all(project.join("crates/sonium-bem/src")).unwrap();
fs::create_dir_all(project.join("crates/sonium-qa/tests")).unwrap();
fs::create_dir_all(project.join("crates/unrelated/src")).unwrap();
fs::write(
project.join("crates/sonium-bem/src/linear.rs"),
r#"
pub enum BasisOrder { Linear, Quadratic }
pub fn standard_assembly(order: BasisOrder) {
if matches!(order, BasisOrder::Linear) {}
}
pub fn stabilized_assembly(order: BasisOrder) {
if matches!(order, BasisOrder::Linear) {}
}
pub fn incident_rhs(order: BasisOrder) {
if matches!(order, BasisOrder::Linear) {}
}
pub fn validate_backend(order: BasisOrder) {
if matches!(order, BasisOrder::Linear) {}
}
"#,
)
.unwrap();
fs::write(
project.join("crates/sonium-qa/tests/linear_regression.rs"),
r#"
pub fn physical_pressure() {
let order = BasisOrder::Linear;
export(order);
}
#[test]
fn linear_regression() {
let order = BasisOrder::Linear;
assert_supported(order);
}
"#,
)
.unwrap();
fs::write(
project.join("crates/unrelated/src/ignored.rs"),
"pub fn excluded_path() { let _ = BasisOrder::Linear; }\n",
)
.unwrap();
let cg = TokenSave::init(project).await.unwrap();
cg.index_all().await.unwrap();
let builder = ContextBuilder::new(cg.db(), project);
let context = builder
.build_context(
"Find every code path specific to BasisOrder::Linear, including assembly, validation, output, and regression tests.",
&BuildContextOptions {
max_nodes: 10,
search_limit: 2,
max_per_file: Some(2),
extra_keywords: vec!["BasisOrder::Linear".to_string()],
path_include: vec![
"crates/sonium-bem".to_string(),
"crates/sonium-qa".to_string(),
],
..Default::default()
},
)
.await
.unwrap();
let names: HashSet<&str> = context
.entry_points
.iter()
.map(|node| node.name.as_str())
.collect();
let expected = HashSet::from([
"standard_assembly",
"stabilized_assembly",
"incident_rhs",
"validate_backend",
"physical_pressure",
"linear_regression",
]);
assert!(
expected.is_subset(&names),
"entry points: {:?}",
context.entry_points
);
assert!(context.entry_points.len() <= expected.len() + 2);
assert_eq!(context.seen_node_ids.len(), context.entry_points.len());
assert!(!names.contains("excluded_path"));
}
#[tokio::test]
async fn conceptual_context_discovers_executable_body_owner() {
use std::fs;
use tempfile::TempDir;
use tokensave::context::ContextBuilder;
use tokensave::tokensave::TokenSave;
let dir = TempDir::new().unwrap();
let project = dir.path();
fs::create_dir_all(project.join("src")).unwrap();
fs::write(
project.join("src/solver.rs"),
r#"
pub fn run_policy(frequencies: &[f64]) {
let mut preconditioner_cache = None;
for frequency in frequencies {
let retry = preconditioner_cache.is_none();
if retry {
preconditioner_cache = Some(*frequency);
}
let residual = frequency.abs();
record_diagnostics(residual);
}
}
fn record_diagnostics(_residual: f64) {}
"#,
)
.unwrap();
let cg = TokenSave::init(project).await.unwrap();
cg.index_all().await.unwrap();
let builder = ContextBuilder::new(cg.db(), project);
let context = builder
.build_context(
"frequency retry preconditioner cache diagnostics residual",
&BuildContextOptions {
search_limit: 5,
max_nodes: 20,
..Default::default()
},
)
.await
.unwrap();
assert!(
context
.entry_points
.iter()
.any(|node| node.name == "run_policy"),
"behavioral owner should be discoverable from body concepts; got {:?}",
context
.entry_points
.iter()
.map(|node| &node.name)
.collect::<Vec<_>>()
);
}
#[tokio::test]
async fn conceptual_context_associates_local_control_flow_with_owner() {
use std::fs;
use tempfile::TempDir;
use tokensave::context::ContextBuilder;
use tokensave::tokensave::TokenSave;
let dir = TempDir::new().unwrap();
let project = dir.path();
fs::create_dir_all(project.join("src")).unwrap();
fs::write(
project.join("src/runner.rs"),
r#"
pub fn execute(frequencies: &[f64]) {
let mut cached_precond = None;
let rebuild_every = 8;
for (freq_idx, frequency) in frequencies.iter().enumerate() {
let must_rebuild = cached_precond.is_none() || freq_idx % rebuild_every == 0;
if must_rebuild {
cached_precond = Some(*frequency);
}
}
}
"#,
)
.unwrap();
let cg = TokenSave::init(project).await.unwrap();
cg.index_all().await.unwrap();
let builder = ContextBuilder::new(cg.db(), project);
let context = builder
.build_context(
"preconditioner cache rebuild",
&BuildContextOptions {
search_limit: 5,
max_nodes: 20,
..Default::default()
},
)
.await
.unwrap();
assert!(
context
.entry_points
.iter()
.any(|node| node.name == "execute"),
"local branch identifiers should retrieve their executable owner"
);
}
#[tokio::test]
async fn requested_type_expands_to_its_behavioral_api() {
use std::fs;
use tempfile::TempDir;
use tokensave::context::ContextBuilder;
use tokensave::tokensave::TokenSave;
let dir = TempDir::new().unwrap();
let project = dir.path();
fs::create_dir_all(project.join("src")).unwrap();
fs::write(
project.join("src/source.rs"),
r#"
pub struct Source {
gain: f64,
}
impl Source {
pub fn amplitude_towards(&self, angle: f64) -> f64 {
self.gain * angle.cos()
}
pub fn polar_weight(&self, angle: f64) -> f64 {
self.gain * angle.sin()
}
}
"#,
)
.unwrap();
let cg = TokenSave::init(project).await.unwrap();
cg.index_all().await.unwrap();
let builder = ContextBuilder::new(cg.db(), project);
let context = builder
.build_context(
"Source behavior",
&BuildContextOptions {
search_limit: 10,
max_nodes: 20,
..Default::default()
},
)
.await
.unwrap();
let names: Vec<_> = context
.entry_points
.iter()
.map(|node| node.name.as_str())
.collect();
assert!(
names.contains(&"amplitude_towards"),
"entry points: {names:?}"
);
assert!(names.contains(&"polar_weight"), "entry points: {names:?}");
}
#[tokio::test]
async fn executable_body_index_is_replaced_by_incremental_sync() {
use std::fs;
use tempfile::TempDir;
use tokensave::context::ContextBuilder;
use tokensave::tokensave::TokenSave;
let dir = TempDir::new().unwrap();
let project = dir.path();
fs::create_dir_all(project.join("src")).unwrap();
let source_path = project.join("src/policy.rs");
fs::write(
&source_path,
"pub fn policy() { let cached_precond = true; let must_rebuild = cached_precond; }\n",
)
.unwrap();
let cg = TokenSave::init(project).await.unwrap();
cg.index_all().await.unwrap();
let options = BuildContextOptions {
search_limit: 5,
max_nodes: 20,
..Default::default()
};
let builder = ContextBuilder::new(cg.db(), project);
let before = builder
.build_context("preconditioner rebuild", &options)
.await
.unwrap();
assert!(before.entry_points.iter().any(|node| node.name == "policy"));
fs::write(
&source_path,
"pub fn policy() { let session_rotation = true; let renew_credentials = session_rotation; }\n",
)
.unwrap();
cg.sync().await.unwrap();
let old_terms = builder
.build_context("preconditioner rebuild", &options)
.await
.unwrap();
assert!(!old_terms
.entry_points
.iter()
.any(|node| node.name == "policy"));
let new_terms = builder
.build_context("session rotation credentials renewal", &options)
.await
.unwrap();
assert!(new_terms
.entry_points
.iter()
.any(|node| node.name == "policy"));
}