mod common;
use common::fixtures;
use common::TestDb;
use recall_echo::graph::gc::GcConfig;
use recall_echo::graph::types::NewRelationship;
#[tokio::test]
async fn gc_dry_run_no_mutations() {
let db = TestDb::new().await;
let entities = fixtures::simple_entities();
let rels = fixtures::simple_relationships();
for e in &entities {
db.graph.add_entity(e.clone()).await.unwrap();
}
for r in &rels {
db.graph.add_relationship(r.clone()).await.unwrap();
}
let before = db.graph.stats().await.unwrap();
let config = GcConfig {
dry_run: true,
..Default::default()
};
let report = db.graph.run_gc(&config).await.unwrap();
let after = db.graph.stats().await.unwrap();
assert_eq!(
before.entity_count, after.entity_count,
"entities unchanged"
);
assert_eq!(
before.relationship_count, after.relationship_count,
"relationships unchanged"
);
let _ = report;
}
#[tokio::test]
async fn gc_execute_removes_low_confidence_relationship() {
let db = TestDb::new().await;
let entities = fixtures::simple_entities();
for e in &entities {
db.graph.add_entity(e.clone()).await.unwrap();
}
let weak_rel = NewRelationship {
from_entity: "Rust".to_string(),
to_entity: "Daniel".to_string(),
rel_type: "WEAK_LINK".to_string(),
description: Some("barely connected".to_string()),
confidence: Some(0.05),
source: Some("test".to_string()),
};
db.graph.add_relationship(weak_rel).await.unwrap();
let before = db.graph.stats().await.unwrap();
assert_eq!(before.relationship_count, 1);
let config = GcConfig {
dry_run: false,
dead_confidence: 0.2,
dead_min_age_days: 0, stale_days: 0,
stale_confidence: 0.5,
protect_pipeline: true,
};
let _report = db.graph.run_gc(&config).await.unwrap();
let after = db.graph.stats().await.unwrap();
assert!(
after.relationship_count <= before.relationship_count,
"GC execute should not increase relationships"
);
}
#[tokio::test]
async fn gc_protects_pipeline_entities() {
let db = TestDb::new().await;
let pipeline_entity = recall_echo::graph::types::NewEntity {
name: "Learning Thread".to_string(),
entity_type: recall_echo::graph::types::EntityType::Thread,
abstract_text: "A thought in development".to_string(),
overview: None,
content: None,
attributes: Some(serde_json::json!({"pipeline_stage": "thoughts"})),
source: Some("pipeline:learning".to_string()),
};
db.graph.add_entity(pipeline_entity).await.unwrap();
let config = GcConfig {
dry_run: false,
protect_pipeline: true,
..Default::default()
};
let _report = db.graph.run_gc(&config).await.unwrap();
let found = db.graph.get_entity("Learning Thread").await.unwrap();
assert!(
found.is_some(),
"pipeline entity should be protected from GC"
);
}
#[tokio::test]
async fn gc_on_empty_graph() {
let db = TestDb::new().await;
let config = GcConfig::default();
let report = db.graph.run_gc(&config).await.unwrap();
let _ = report;
let stats = db.graph.stats().await.unwrap();
assert_eq!(stats.entity_count, 0);
}