125 lines
3.4 KiB
Rust
125 lines
3.4 KiB
Rust
//! 会话树与 JSONL 持久化的单元测试。
|
|
//! Unit tests for session trees and JSONL persistence.
|
|
|
|
use focus_core::model::Message;
|
|
use focus_harness::session::{SessionEntry, SessionStore, SessionTree};
|
|
use std::path::PathBuf;
|
|
|
|
fn temp_dir(tag: &str) -> PathBuf {
|
|
let d = std::env::temp_dir().join(format!(
|
|
"focus-harness-session-{}-{}",
|
|
tag,
|
|
std::process::id()
|
|
));
|
|
let _ = std::fs::remove_dir_all(&d);
|
|
std::fs::create_dir_all(&d).unwrap();
|
|
d
|
|
}
|
|
|
|
#[test]
|
|
fn appends_and_loads_entries() {
|
|
let dir = temp_dir("append");
|
|
let store = SessionStore::new(&dir);
|
|
store
|
|
.append(
|
|
"s1",
|
|
&SessionEntry::new("e1".into(), None, Message::user_text("hi")),
|
|
)
|
|
.unwrap();
|
|
store
|
|
.append(
|
|
"s1",
|
|
&SessionEntry::new("e2".into(), Some("e1".into()), Message::user_text("there")),
|
|
)
|
|
.unwrap();
|
|
|
|
let entries = store.load("s1").unwrap();
|
|
assert_eq!(entries.len(), 2);
|
|
assert_eq!(entries[0].id, "e1");
|
|
assert_eq!(entries[0].parent_id, None);
|
|
assert_eq!(entries[1].id, "e2");
|
|
assert_eq!(entries[1].parent_id.as_deref(), Some("e1"));
|
|
assert!(matches!(entries[0].message, Message::User(_)));
|
|
}
|
|
|
|
#[test]
|
|
fn next_entry_id_is_incremental() {
|
|
let dir = temp_dir("seq");
|
|
let store = SessionStore::new(&dir);
|
|
assert_eq!(store.next_entry_id("s1").unwrap(), "e1");
|
|
store
|
|
.append(
|
|
"s1",
|
|
&SessionEntry::new("e1".into(), None, Message::user_text("a")),
|
|
)
|
|
.unwrap();
|
|
assert_eq!(store.next_entry_id("s1").unwrap(), "e2");
|
|
store
|
|
.append(
|
|
"s1",
|
|
&SessionEntry::new("e3".into(), Some("e1".into()), Message::user_text("b")),
|
|
)
|
|
.unwrap();
|
|
// e3 已存在 → 下一个是 e4。
|
|
// e3 exists → the next is e4.
|
|
assert_eq!(store.next_entry_id("s1").unwrap(), "e4");
|
|
}
|
|
|
|
#[test]
|
|
fn lists_sessions() {
|
|
let dir = temp_dir("list");
|
|
let store = SessionStore::new(&dir);
|
|
store
|
|
.append(
|
|
"alpha",
|
|
&SessionEntry::new("e1".into(), None, Message::user_text("a")),
|
|
)
|
|
.unwrap();
|
|
store
|
|
.append(
|
|
"beta",
|
|
&SessionEntry::new("e1".into(), None, Message::user_text("b")),
|
|
)
|
|
.unwrap();
|
|
let ids = store.list_sessions().unwrap();
|
|
assert_eq!(ids, vec!["alpha".to_string(), "beta".to_string()]);
|
|
}
|
|
|
|
fn tree() -> SessionTree {
|
|
let entries = vec![
|
|
SessionEntry::new("e1".into(), None, Message::user_text("root")),
|
|
SessionEntry::new(
|
|
"e2".into(),
|
|
Some("e1".into()),
|
|
Message::user_text("child A"),
|
|
),
|
|
SessionEntry::new(
|
|
"e3".into(),
|
|
Some("e1".into()),
|
|
Message::user_text("child B"),
|
|
),
|
|
SessionEntry::new(
|
|
"e4".into(),
|
|
Some("e3".into()),
|
|
Message::user_text("grandchild"),
|
|
),
|
|
];
|
|
SessionTree::build(entries)
|
|
}
|
|
|
|
#[test]
|
|
fn tree_queries() {
|
|
let t = tree();
|
|
assert_eq!(t.roots().len(), 1);
|
|
assert_eq!(t.roots()[0].id, "e1");
|
|
let children = t.children_of("e1");
|
|
assert_eq!(children.len(), 2);
|
|
let path = t.branch("e4");
|
|
let ids: Vec<&str> = path.iter().map(|e| e.id.as_str()).collect();
|
|
assert_eq!(ids, vec!["e1", "e3", "e4"]);
|
|
let leaves = t.leaf_ids();
|
|
assert_eq!(leaves.len(), 2);
|
|
assert!(leaves.contains(&"e2"));
|
|
assert!(leaves.contains(&"e4"));
|
|
}
|