use std::path::PathBuf;
use std::sync::Arc;
use std::sync::atomic::{AtomicU64, Ordering};
use clawft_core::bootstrap::AppContext;
use clawft_core::session::SessionManager;
use clawft_platform::NativePlatform;
use clawft_types::config::Config;
use clawft_types::session::Session;
static TEST_COUNTER: AtomicU64 = AtomicU64::new(0);
fn temp_dir(prefix: &str) -> PathBuf {
let id = TEST_COUNTER.fetch_add(1, Ordering::Relaxed);
let pid = std::process::id();
std::env::temp_dir().join(format!("clawft_phase1_{prefix}_{pid}_{id}"))
}
#[tokio::test]
async fn test_config_loads_and_initializes_all_subsystems() {
let config = Config::default();
let platform = Arc::new(NativePlatform::new());
let ctx = AppContext::new(config, platform).await.unwrap();
assert!(ctx.tools().is_empty()); assert!(ctx.memory().memory_path().is_absolute());
assert!(ctx.skills().skills_dir().is_absolute());
let _bus = ctx.bus().clone();
}
#[tokio::test]
async fn test_session_persistence_across_restarts() {
let dir = temp_dir("session_persist");
let sessions_dir = dir.join("sessions");
let platform = Arc::new(NativePlatform::new());
{
let mgr = SessionManager::with_dir(platform.clone(), sessions_dir.clone());
let mut session = Session::new("persist-test");
session.add_message("user", "hello", None);
session.add_message("assistant", "hi there", None);
mgr.save_session(&session).await.unwrap();
}
{
let mgr = SessionManager::with_dir(platform.clone(), sessions_dir);
let loaded = mgr.load_session("persist-test").await.unwrap();
assert_eq!(loaded.key, "persist-test");
assert_eq!(loaded.messages.len(), 2);
assert_eq!(loaded.messages[0]["role"], "user");
assert_eq!(loaded.messages[0]["content"], "hello");
assert_eq!(loaded.messages[1]["role"], "assistant");
assert_eq!(loaded.messages[1]["content"], "hi there");
}
let _ = tokio::fs::remove_dir_all(&dir).await;
}
#[tokio::test]
async fn test_fixture_config_loads() {
let fixture_path = concat!(
env!("CARGO_MANIFEST_DIR"),
"/../../tests/fixtures/config.json"
);
let content = tokio::fs::read_to_string(fixture_path).await.unwrap();
let config: Config = serde_json::from_str(&content).unwrap();
assert_eq!(config.agents.defaults.model, clawft_types::config::DEFAULT_LOCAL_LLM_MODEL_ROUTED);
assert!(config.channels.telegram.enabled);
}
#[tokio::test]
async fn test_session_fixture_parses() {
let fixture_path = concat!(
env!("CARGO_MANIFEST_DIR"),
"/../../tests/fixtures/session.jsonl"
);
let content = tokio::fs::read_to_string(fixture_path).await.unwrap();
let lines: Vec<&str> = content.lines().collect();
assert!(lines.len() >= 6, "fixture should have at least 6 lines");
let meta: serde_json::Value = serde_json::from_str(lines[0]).unwrap();
assert_eq!(meta["_type"], "metadata");
for line in &lines[1..] {
let msg: serde_json::Value = serde_json::from_str(line).unwrap();
assert!(msg.get("role").is_some());
assert!(msg.get("content").is_some());
}
}
#[tokio::test]
async fn test_tool_fixture_parses() {
let fixture_path = concat!(
env!("CARGO_MANIFEST_DIR"),
"/../../tests/fixtures/tools/read_file.json"
);
let content = tokio::fs::read_to_string(fixture_path).await.unwrap();
let tool_def: serde_json::Value = serde_json::from_str(&content).unwrap();
assert_eq!(tool_def["type"], "function");
assert_eq!(tool_def["function"]["name"], "read_file");
assert!(
tool_def["function"]["parameters"]["required"]
.as_array()
.unwrap()
.contains(&serde_json::Value::String("path".into()))
);
}
#[tokio::test]
async fn test_session_roundtrip_preserves_metadata() {
let dir = temp_dir("session_meta");
let sessions_dir = dir.join("sessions");
let platform = Arc::new(NativePlatform::new());
let mgr = SessionManager::with_dir(platform, sessions_dir);
let mut session = Session::new("meta-test");
session
.metadata
.insert("agent".into(), serde_json::json!("test-bot"));
session.last_consolidated = 3;
session.add_message("user", "hi", None);
mgr.save_session(&session).await.unwrap();
let loaded = mgr.load_session("meta-test").await.unwrap();
assert_eq!(loaded.last_consolidated, 3);
assert_eq!(loaded.metadata["agent"], "test-bot");
assert_eq!(loaded.messages.len(), 1);
let _ = tokio::fs::remove_dir_all(&dir).await;
}
#[tokio::test]
async fn test_app_context_into_agent_loop() {
let config = Config::default();
let platform = Arc::new(NativePlatform::new());
let ctx = AppContext::new(config, platform).await.unwrap();
let _tx = ctx.bus().inbound_sender();
let agent = ctx.into_agent_loop();
assert_eq!(agent.config().defaults.model, clawft_types::config::DEFAULT_LOCAL_LLM_MODEL_ROUTED);
}