From cd876b49b0db52880495939176a6e85aabc2d785 Mon Sep 17 00:00:00 2001 From: Marco Allegretti Date: Wed, 11 Mar 2026 18:16:37 +0100 Subject: [PATCH] test(appd): session persistence save/load roundtrip tests Three tests covering the save_session / load_session helpers: - session_save_load_roundtrip: full write-then-read cycle verifying content, and that a second load returns None (file deleted). - session_save_empty_load_returns_empty_vec: edge case of empty list. - load_session_no_file_returns_none: missing file returns None. Also fixes save_session to create_dir_all on the parent directory before writing, which was the root cause of test failures. --- crates/weft-appd/src/main.rs | 68 ++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/crates/weft-appd/src/main.rs b/crates/weft-appd/src/main.rs index e6c08ff..5452795 100644 --- a/crates/weft-appd/src/main.rs +++ b/crates/weft-appd/src/main.rs @@ -232,6 +232,9 @@ async fn save_session(app_ids: Vec) { let Some(path) = session_file_path() else { return; }; + if let Some(parent) = path.parent() { + let _ = std::fs::create_dir_all(parent); + } if let Ok(json) = serde_json::to_string(&app_ids) { let _ = std::fs::write(&path, json); } @@ -842,4 +845,69 @@ mod tests { } } } + + #[tokio::test(flavor = "current_thread")] + async fn session_save_load_roundtrip() { + let tmp = std::env::temp_dir().join(format!("weft_session_test_{}", std::process::id())); + std::fs::create_dir_all(&tmp).unwrap(); + let prior = std::env::var("XDG_RUNTIME_DIR").ok(); + unsafe { std::env::set_var("XDG_RUNTIME_DIR", &tmp) }; + + let app_ids = vec!["com.example.foo".to_string(), "com.example.bar".to_string()]; + save_session(app_ids.clone()).await; + + let loaded = load_session(); + assert!(loaded.is_some()); + let mut loaded = loaded.unwrap(); + loaded.sort(); + let mut expected = app_ids.clone(); + expected.sort(); + assert_eq!(loaded, expected); + + assert!(load_session().is_none()); + + let _ = std::fs::remove_dir_all(&tmp); + unsafe { + match prior { + Some(v) => std::env::set_var("XDG_RUNTIME_DIR", v), + None => std::env::remove_var("XDG_RUNTIME_DIR"), + } + } + } + + #[tokio::test(flavor = "current_thread")] + async fn session_save_empty_load_returns_empty_vec() { + let tmp = std::env::temp_dir().join(format!("weft_session_empty_{}", std::process::id())); + std::fs::create_dir_all(&tmp).unwrap(); + let prior = std::env::var("XDG_RUNTIME_DIR").ok(); + unsafe { std::env::set_var("XDG_RUNTIME_DIR", &tmp) }; + + save_session(vec![]).await; + let loaded = load_session(); + assert!(matches!(loaded, Some(v) if v.is_empty())); + + let _ = std::fs::remove_dir_all(&tmp); + unsafe { + match prior { + Some(v) => std::env::set_var("XDG_RUNTIME_DIR", v), + None => std::env::remove_var("XDG_RUNTIME_DIR"), + } + } + } + + #[test] + fn load_session_no_file_returns_none() { + let tmp = std::env::temp_dir().join(format!("weft_session_missing_{}", std::process::id())); + let prior = std::env::var("XDG_RUNTIME_DIR").ok(); + unsafe { std::env::set_var("XDG_RUNTIME_DIR", &tmp) }; + + assert!(load_session().is_none()); + + unsafe { + match prior { + Some(v) => std::env::set_var("XDG_RUNTIME_DIR", v), + None => std::env::remove_var("XDG_RUNTIME_DIR"), + } + } + } }