Sebastian Thielthanks clippye1003d54 years agoHistory
149 lines · 5.8 KB · Rust
RawDownload
mod empty_upwards_until_boundary {    use std::{io, path::Path};     use git_tempfile::remove_dir;     #[test]    fn boundary_must_contain_target_dir() -> crate::Result {        let dir = tempfile::tempdir()?;        let (target, boundary) = (dir.path().join("a"), dir.path().join("b"));        std::fs::create_dir(&target)?;        std::fs::create_dir(&boundary)?;        assert!(matches!(remove_dir::empty_upward_until_boundary(&target, &boundary),                            Err(err) if err.kind() == io::ErrorKind::InvalidInput));        assert!(target.is_dir());        assert!(boundary.is_dir());        Ok(())    }    #[test]    fn target_directory_non_existing_causes_existing_parents_not_to_be_deleted() -> crate::Result {        let dir = tempfile::tempdir()?;        let parent = dir.path().join("a");        std::fs::create_dir(&parent)?;        let target = parent.join("not-existing");        assert_eq!(remove_dir::empty_upward_until_boundary(&target, dir.path())?, target);        assert!(            parent.is_dir(),            "the parent wasn't touched if the target already wasn't present"        );        Ok(())    }     #[test]    fn target_directory_being_a_file_immediately_fails() -> crate::Result {        let dir = tempfile::tempdir()?;        let target = dir.path().join("actually-a-file");        std::fs::write(&target, &[42])?;        assert!(remove_dir::empty_upward_until_boundary(&target, dir.path()).is_err()); // TODO: check for IsNotADirectory when it becomes stable        assert!(target.is_file(), "it didn't touch the file");        assert!(dir.path().is_dir(), "it won't touch the boundary");        Ok(())    }    #[test]    fn boundary_being_the_target_dir_always_succeeds_and_we_do_nothing() -> crate::Result {        let dir = tempfile::tempdir()?;        assert_eq!(            remove_dir::empty_upward_until_boundary(dir.path(), dir.path())?,            dir.path()        );        assert!(dir.path().is_dir(), "it won't touch the boundary");        Ok(())    }    #[test]    fn a_directory_which_doesnt_exist_to_start_with_is_ok() -> crate::Result {        let dir = tempfile::tempdir()?;        let target = dir.path().join("does-not-exist");        assert_eq!(remove_dir::empty_upward_until_boundary(&target, dir.path())?, target);        assert!(dir.path().is_dir(), "it won't touch the boundary");        Ok(())    }    #[test]    fn boundary_directory_doesnt_have_to_exist_either_if_the_target_doesnt() -> crate::Result {        let boundary = Path::new("/boundary");        let target = Path::new("/boundary/target");        assert_eq!(remove_dir::empty_upward_until_boundary(target, boundary)?, target);        Ok(())    }    #[test]    fn nested_directory_deletion_works() -> crate::Result {        let dir = tempfile::tempdir()?;        let nested = dir.path().join("a").join("b").join("to-delete");        std::fs::create_dir_all(&nested)?;        assert_eq!(remove_dir::empty_upward_until_boundary(&nested, dir.path())?, nested);        assert!(!nested.is_dir(), "it actually deleted the nested directory");        assert!(!nested.parent().unwrap().is_dir(), "parent one was deleted");        assert!(            !nested.parent().unwrap().parent().unwrap().is_dir(),            "parent two was deleted"        );        assert!(dir.path().is_dir(), "it won't touch the boundary");        Ok(())    }} mod empty_depth_first {    use std::{        fs::{create_dir, create_dir_all},        path::Path,    };     #[test]    fn non_empty_anywhere_and_deletion_fails() -> crate::Result {        let dir = tempfile::TempDir::new()?;        let touch = |base: &Path, name: &str| create_dir_all(base).and_then(|_| std::fs::write(base.join(name), b""));         let nested_parent = dir.path().join("a");        touch(&nested_parent, "hello.ext")?;         let tree_parent = dir.path().join("tree");        touch(&tree_parent.join("a").join("b"), "hello.ext")?;        create_dir_all(tree_parent.join("one").join("two").join("empty"))?;         assert!(git_tempfile::remove_dir::empty_depth_first(nested_parent).is_err());        Ok(())    }     #[test]    fn nested_empty_and_single_empty_delete_successfully() {        let dir = tempfile::TempDir::new().unwrap();        let nested_parent = dir.path().join("a");        let nested = nested_parent.join("b").join("leaf");        create_dir_all(nested).unwrap();         let single_parent = dir.path().join("single");        create_dir(&single_parent).unwrap();         let tree_parent = dir.path().join("tree");        create_dir_all(tree_parent.join("a").join("b")).unwrap();        create_dir_all(tree_parent.join("one").join("two").join("three")).unwrap();        create_dir_all(tree_parent.join("c")).unwrap();        for empty in &[nested_parent, single_parent, tree_parent] {            git_tempfile::remove_dir::empty_depth_first(empty).unwrap();        }    }} /// We assume that all checks above also apply to the iterator, so won't repeat them here/// Test outside interference onlymod iter {    use git_tempfile::remove_dir;     #[test]    fn racy_directory_creation_during_deletion_always_wins_immediately() -> crate::Result {        let dir = tempfile::tempdir()?;        let nested = dir.path().join("a").join("b").join("to-delete");        std::fs::create_dir_all(&nested)?;         let mut it = remove_dir::Iter::new(&nested, dir.path())?;        assert_eq!(it.next().expect("item")?, nested, "delete leaves directory");         // recreate the deleted directory in racy fashion, causing the next-to-delete directory not to be empty.        std::fs::create_dir(&nested)?;        assert!(            it.next().expect("err item").is_err(),            "cannot delete non-empty directory" // TODO: check for IsADirectory when it becomes stable        );        assert!(it.next().is_none(), "iterator is depleted");        Ok(())    }}