//! Infrastructure tests for local model-server adapters. use std::path::PathBuf; use std::sync::Arc; use domain::model_server::{ ExecutablePath, LocalModelRef, LocalModelServerConfig, LocalModelServerKind, ModelPath, ModelServerEndpoint, StopPolicy, }; use domain::ports::{FileSystem, ModelServerRegistry, ModelServerRuntime, RemotePath}; use domain::LocalModelServerId; use infrastructure::{FsModelServerRegistry, LlamaCppRuntime, LocalFileSystem}; use uuid::Uuid; struct TempDir(PathBuf); impl TempDir { fn new() -> Self { let path = std::env::temp_dir().join(format!("idea-model-server-{}", Uuid::new_v4())); std::fs::create_dir_all(&path).unwrap(); Self(path) } fn app_data_dir(&self) -> String { self.0.to_string_lossy().into_owned() } fn child(&self, name: &str) -> RemotePath { RemotePath::new(self.0.join(name).to_string_lossy().into_owned()) } } impl Drop for TempDir { fn drop(&mut self) { let _ = std::fs::remove_dir_all(&self.0); } } fn sid(n: u128) -> LocalModelServerId { LocalModelServerId::from_uuid(Uuid::from_u128(n)) } fn config(id: LocalModelServerId, port: u16) -> LocalModelServerConfig { let binary = std::env::current_exe() .unwrap() .to_string_lossy() .into_owned(); LocalModelServerConfig::new( id, LocalModelServerKind::LlamaCpp, "Local Qwen", ModelServerEndpoint::new(format!("http://localhost:{port}/v1"), port).unwrap(), LocalModelRef::new( "qwen", "Qwen", Some(ModelPath::new("/models/qwen.gguf").unwrap()), "qwen3-coder-30b", ) .unwrap(), Some(ExecutablePath::new(binary).unwrap()), vec!["--ctx-size".to_owned(), "8192".to_owned()], true, StopPolicy::StopOnAppExit, ) .unwrap() } #[test] fn llamacpp_runtime_builds_structured_argv() { let spec = LlamaCppRuntime::new() .build_spawn_spec(&config(sid(1), 8080)) .unwrap(); assert_eq!( spec.command, std::env::current_exe().unwrap().to_string_lossy() ); assert_eq!( spec.args, vec![ "--model", "/models/qwen.gguf", "--port", "8080", "--ctx-size", "8192" ] ); assert!(spec.context_plan.is_none()); } #[tokio::test] async fn fs_model_server_registry_roundtrips_global_json() { let tmp = TempDir::new(); let fs: Arc = Arc::new(LocalFileSystem::new()); let registry = FsModelServerRegistry::new(Arc::clone(&fs), tmp.app_data_dir()); let first = config(sid(2), 8081); registry.save(first.clone()).await.unwrap(); assert_eq!(registry.get(&first.id).await.unwrap(), Some(first.clone())); assert_eq!(registry.list().await.unwrap(), vec![first.clone()]); assert!( fs.exists(&tmp.child("model-servers.json")).await.unwrap(), "registry must live in global app-data dir" ); let updated = config(sid(2), 8082); registry.save(updated.clone()).await.unwrap(); assert_eq!(registry.list().await.unwrap(), vec![updated]); }