Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
对话链路: 4 缝测试 (Tauri→Kernel / Kernel→LLM / LLM→UI / 流式生命周期) Hands链路: 3 缝测试 (工具路由 / 执行回调 / 通用工具) 记忆链路: 3 缝测试 (FTS5存储 / 模式检索 / 去重) 冒烟测试: 3 Rust + 8 TypeScript 全量 PASS - Kernel::boot_with_driver() 测试辅助方法 - 全量 cargo test 0 回归 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
109 lines
3.6 KiB
Rust
109 lines
3.6 KiB
Rust
//! Memory chain seam tests
|
|
//!
|
|
//! Verifies the integration seams in the memory pipeline:
|
|
//! 1. Extract & store: experience → FTS5 write
|
|
//! 2. Retrieve & inject: FTS5 search → memory found
|
|
//! 3. Dedup: same experience not duplicated (reuse_count incremented)
|
|
|
|
use std::sync::Arc;
|
|
use zclaw_growth::{
|
|
ExperienceStore, Experience, VikingAdapter,
|
|
storage::SqliteStorage,
|
|
};
|
|
|
|
async fn test_store() -> ExperienceStore {
|
|
let sqlite = SqliteStorage::in_memory().await;
|
|
let viking = Arc::new(VikingAdapter::new(Arc::new(sqlite)));
|
|
ExperienceStore::new(viking)
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Seam 1: Extract & Store — experience written to FTS5
|
|
// ---------------------------------------------------------------------------
|
|
|
|
#[tokio::test]
|
|
async fn seam_experience_store_and_retrieve() {
|
|
let store = test_store().await;
|
|
|
|
let exp = Experience::new(
|
|
"agent-001",
|
|
"高 CPU 使用率告警频繁",
|
|
"生产环境 CPU 使用率告警",
|
|
vec!["检查进程列表".to_string(), "重启服务".to_string()],
|
|
"已解决",
|
|
);
|
|
|
|
store.store_experience(&exp).await.expect("store experience");
|
|
|
|
// Retrieve by agent
|
|
let found = store.find_by_agent("agent-001").await.expect("find");
|
|
assert_eq!(found.len(), 1, "should find exactly one experience");
|
|
assert_eq!(found[0].pain_pattern, "高 CPU 使用率告警频繁");
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Seam 2: Retrieve by pattern — FTS5 search finds relevant experiences
|
|
// ---------------------------------------------------------------------------
|
|
|
|
#[tokio::test]
|
|
async fn seam_experience_pattern_search() {
|
|
let store = test_store().await;
|
|
|
|
// Store multiple experiences
|
|
let exp1 = Experience::new(
|
|
"agent-001",
|
|
"数据库连接超时",
|
|
"PostgreSQL 连接池耗尽",
|
|
vec!["增加连接池大小".to_string()],
|
|
"已解决",
|
|
);
|
|
let exp2 = Experience::new(
|
|
"agent-001",
|
|
"前端白屏问题",
|
|
"React 渲染错误",
|
|
vec!["检查错误边界".to_string()],
|
|
"已修复",
|
|
);
|
|
|
|
store.store_experience(&exp1).await.expect("store exp1");
|
|
store.store_experience(&exp2).await.expect("store exp2");
|
|
|
|
// Search for database-related experience
|
|
let results = store.find_by_pattern("agent-001", "数据库 连接").await.expect("search");
|
|
assert!(!results.is_empty(), "FTS5 should find database experience");
|
|
assert!(
|
|
results.iter().any(|e| e.pain_pattern.contains("数据库")),
|
|
"should match database experience, got: {:?}",
|
|
results
|
|
);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Seam 3: Dedup — same pain_pattern increments reuse_count
|
|
// ---------------------------------------------------------------------------
|
|
|
|
#[tokio::test]
|
|
async fn seam_experience_dedup() {
|
|
let store = test_store().await;
|
|
|
|
let exp = Experience::new(
|
|
"agent-001",
|
|
"内存泄漏检测",
|
|
"服务运行一段时间后内存持续增长",
|
|
vec!["分析 heap dump".to_string()],
|
|
"已修复",
|
|
);
|
|
|
|
// Store twice with same agent_id and pain_pattern
|
|
store.store_experience(&exp).await.expect("first store");
|
|
store.store_experience(&exp).await.expect("second store (dedup)");
|
|
|
|
let all = store.find_by_agent("agent-001").await.expect("find");
|
|
assert_eq!(all.len(), 1, "dedup should keep only one experience");
|
|
assert!(
|
|
all[0].reuse_count >= 1,
|
|
"reuse_count should be incremented, got: {}",
|
|
all[0].reuse_count
|
|
);
|
|
}
|