//! L1 integration tests for [`LocalFileSystem`] against a real temp directory. use std::path::PathBuf; use domain::ports::{FileSystem, FsError, RemotePath}; use infrastructure::LocalFileSystem; use uuid::Uuid; /// A unique scratch directory under the OS temp dir, cleaned up on drop. struct TempDir(PathBuf); impl TempDir { fn new() -> Self { let p = std::env::temp_dir().join(format!("idea-l1-{}", Uuid::new_v4())); std::fs::create_dir_all(&p).unwrap(); Self(p) } fn child(&self, name: &str) -> RemotePath { RemotePath::new(self.0.join(name).to_string_lossy().into_owned()) } fn path(&self) -> RemotePath { RemotePath::new(self.0.to_string_lossy().into_owned()) } } impl Drop for TempDir { fn drop(&mut self) { let _ = std::fs::remove_dir_all(&self.0); } } #[tokio::test] async fn write_then_read_roundtrips() { let tmp = TempDir::new(); let fs = LocalFileSystem::new(); let file = tmp.child("hello.txt"); fs.write(&file, b"bonjour").await.unwrap(); let back = fs.read(&file).await.unwrap(); assert_eq!(back, b"bonjour"); } #[tokio::test] async fn exists_reflects_presence() { let tmp = TempDir::new(); let fs = LocalFileSystem::new(); let file = tmp.child("maybe.txt"); assert!(!fs.exists(&file).await.unwrap()); fs.write(&file, b"x").await.unwrap(); assert!(fs.exists(&file).await.unwrap()); } #[tokio::test] async fn create_dir_all_and_list() { let tmp = TempDir::new(); let fs = LocalFileSystem::new(); let nested = tmp.child("a/b/c"); fs.create_dir_all(&nested).await.unwrap(); assert!(fs.exists(&nested).await.unwrap()); // Put a file and a dir at the top level, then list them. fs.write(&tmp.child("file.txt"), b"y").await.unwrap(); let entries = fs.list(&tmp.path()).await.unwrap(); let names: Vec<&str> = entries.iter().map(|e| e.name.as_str()).collect(); assert!(names.contains(&"file.txt")); assert!(names.contains(&"a")); let dir_entry = entries.iter().find(|e| e.name == "a").unwrap(); assert!(dir_entry.is_dir); let file_entry = entries.iter().find(|e| e.name == "file.txt").unwrap(); assert!(!file_entry.is_dir); } #[tokio::test] async fn read_missing_maps_to_not_found() { let tmp = TempDir::new(); let fs = LocalFileSystem::new(); let err = fs.read(&tmp.child("nope.txt")).await.unwrap_err(); assert!(matches!(err, FsError::NotFound(_)), "got {err:?}"); }