test_dir-0.2.0/.cargo_vcs_info.json0000644000000001360000000000100126500ustar { "git": { "sha1": "3a4369b31d2d5816a566e9b2aef27939778b1f41" }, "path_in_vcs": "" }test_dir-0.2.0/Cargo.toml0000644000000016210000000000100106460ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "test_dir" version = "0.2.0" authors = ["Rafał Pachołek "] description = "Easy creation of temporary file structure for test purpose." readme = "README.md" keywords = [ "test", "dir", "file", "directory", "temp", ] categories = ["development-tools::testing"] license = "MIT" repository = "https://github.com/rpacholek/test_dir" [dependencies.rand] version = "0.8" test_dir-0.2.0/Cargo.toml.orig000064400000000000000000000006430072674642500143620ustar 00000000000000[package] name = "test_dir" version = "0.2.0" authors = ["Rafał Pachołek "] edition = "2018" license = "MIT" description = "Easy creation of temporary file structure for test purpose." readme = "README.md" repository = "https://github.com/rpacholek/test_dir" keywords = [ "test", "dir", "file", "directory", "temp" ] categories = [ "development-tools::testing" ] [dependencies] rand = "0.8" test_dir-0.2.0/LICENSE000064400000000000000000000020400072674642500124710ustar 00000000000000Copyright 2019 Rafał Pachołek Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. test_dir-0.2.0/README.md000064400000000000000000000012460072674642500127520ustar 00000000000000# TestDir Fast creation of file structure for testing purpose. ## Getting Started Add the following dependency to Cargo manifest: ```toml [dependencies] test_dir = "0.1.0" ``` ## Example ```rust use test_dir::{TestDir,FileType,DirBuilder}; { let temp = TestDir::temp() .create("test/dir", FileType::Dir) .create("test/file", FileType::EmptyFile) .create("test/random_file", FileType::RandomFile(100)) .create("otherdir/zero_file", FileType::ZeroFile(100)); let path: PathBuf = temp.path("test/random_file"); assert!(path.exists()); } // temp out-of-scope -> temp dir deleted ``` ## License Licensed under MIT license, ([LICENSE](LICENSE)) test_dir-0.2.0/src/lib.rs000064400000000000000000000264260072674642500134050ustar 00000000000000//! # test_dir //! //! `TestDir` is a temporary directory builder. The target is to define a file structure for test purpose. //! It is not recommended to use in non-test environment. //! //! ``` //! use std::path::PathBuf; //! use test_dir::{TestDir,FileType,DirBuilder}; //! //! let temp = TestDir::temp() //! .create("test/dir", FileType::Dir) //! .create("test/file", FileType::EmptyFile) //! .create("test/random_file", FileType::RandomFile(100)) //! .create("otherdir/zero_file", FileType::ZeroFile(100)); //! //! let path: PathBuf = temp.path("test/random_file"); //! assert!(path.exists()); //! ``` use rand::distributions::Alphanumeric; use rand::{thread_rng, Rng}; use std::fs; use std::io::prelude::*; use std::io::BufWriter; use std::path::{Path, PathBuf}; /// Supported file types with TestDir #[derive(PartialEq, Debug)] pub enum FileType { /// Create empty file EmptyFile, /// Create a file with random content of the given size RandomFile(usize), /// Create a file with a given len of "0"s ZeroFile(usize), //ContentFile(&dyn std::io::Read), /// Create a directory Dir, } /// Temporary directory pub struct TempDir { path: PathBuf, delete: PathBuf, } impl TempDir { /// Try to create a temporary directory inside system tmp directory. pub fn temp() -> std::io::Result { let mut temp = std::env::temp_dir().to_path_buf(); temp.push(TempDir::random_name()); TempDir::create(temp.as_path()) } /// Try to create a temporary directory inside the current directory. pub fn current_rnd() -> std::io::Result { let mut temp = std::env::current_dir()?.to_path_buf(); temp.push(TempDir::random_name()); TempDir::create(temp.as_path()) } /// Try to create a temporary directory with a given path inside the current directory. pub fn current(path: &Path) -> std::io::Result { let mut temp = std::env::current_dir()?.to_path_buf(); temp.push(path); TempDir::create(temp.as_path()) } /// Get the path of the temporary directory. pub fn path(&self) -> PathBuf { self.path.clone() } // Helper functions fn create(path: &Path) -> std::io::Result { let mut p = path; while let Some(ppath) = p.parent() { if ppath.exists() { break; } p = ppath; } fs::create_dir_all(&path)?; Ok(TempDir { path: path.to_path_buf(), delete: p.to_path_buf(), }) } fn random_name() -> String { // https://stackoverflow.com/a/65478580/113632 thread_rng() .sample_iter(&Alphanumeric) .map(char::from) .take(8) .collect() } } impl Drop for TempDir { /// Delete the created directory tree. fn drop(&mut self) { let _ = fs::remove_dir_all(self.delete.as_path()); } } /// Test directory creator pub struct TestDir { // Directory lifetime _tempdir: Option, root: PathBuf, files: Vec, dirs: Vec, } /// File structure builder trait pub trait DirBuilder { /// Create a file or directory under the `path` fn create(self, path: &str, filetype: FileType) -> Self; /// Remove a file or directory under the `path` fn remove(self, path: &str) -> Self; /// Prefix `path` with the current context of the DirBuilder fn path(&self, path: &str) -> PathBuf; /// Return the root path to the temporary directory fn root(&self) -> &Path; } impl TestDir { /// Creates if possible a temporary directory pub fn temp() -> Self { if let Ok(tempdir) = TempDir::temp() { TestDir::new(tempdir) } else { panic!("Cannot create temp dir in system temp"); } } /// Creates if possible a temporary directory with random name inside the current directory pub fn current_rnd() -> Self { if let Ok(tempdir) = TempDir::current_rnd() { TestDir::new(tempdir) } else { panic!("Cannot create temp dir in current directory") } } /// Creates if possible a temporary directory specified in `path` relative to the current directory pub fn current(path: &str) -> Self { let path = Path::new(path); if let Ok(tempdir) = TempDir::current(path) { TestDir::new(tempdir) } else { panic!("Cannot create dir in current directory") } } /// Returns all files created with DirBuilder pub fn get_files<'a>(&self) -> &Vec { &self.files } /// Returns all directories created with DirBuilder pub fn get_dirs<'a>(&self) -> &Vec { &self.dirs } /* fn load(&mut self, path: &Path) { } */ // Helper functions fn new(tempdir: TempDir) -> Self { let root = tempdir.path().to_path_buf(); Self { _tempdir: Some(tempdir), root, files: vec![], dirs: vec![], } } fn create_dir(&mut self, path: &Path) -> std::io::Result<()> { let mut build_path = self.root.clone(); build_path.push(path); let result = fs::create_dir_all(build_path.as_path()); if let Ok(_) = result { self.dirs.push(build_path); } result } fn create_file(&mut self, path: &Path, filetype: FileType) -> std::io::Result<()> { let mut build_path = self.root.clone(); build_path.push(path); let file = fs::File::create(build_path.as_path()); if file.is_err() { panic!("Create file {:?} - {:?}", build_path, file); } let file = file?; let mut buffer = BufWriter::new(file); match filetype { FileType::EmptyFile => { /* pass */ } FileType::ZeroFile(size) => { for _ in 0..size { let _ = buffer.write(b"0")?; } } FileType::RandomFile(size) => { let mut numbuf: Vec = vec![]; let mut rng = rand::thread_rng(); for _ in 0..size { numbuf.push(rng.gen()); } let _ = buffer.write(numbuf.as_slice())?; } _ => { /* Dir - already created in create_dir */ } }; self.files.push(build_path); Ok(()) } fn remove_file(&mut self, path: &Path) -> std::io::Result<()> { let mut build_path = self.root.clone(); build_path.push(path); if build_path.exists() { if build_path.is_dir() { fs::remove_dir_all(build_path)?; } else if build_path.is_file() { fs::remove_file(build_path)?; } } Ok(()) } } impl DirBuilder for TestDir { /// Create a file or directory under the `path` fn create(mut self, path: &str, filetype: FileType) -> Self { let path = Path::new(path); if path.is_absolute() { panic!("Only relative paths are allowed."); } if filetype == FileType::Dir { let _ = self.create_dir(path).unwrap(); } else { if let Some(p) = path.parent() { let _ = self.create_dir(p).unwrap(); } // else { assume that current dir exists } let _ = self.create_file(path, filetype).unwrap(); } self } /// Remove a file or directory under the `path` fn remove(mut self, path: &str) -> Self { let path = Path::new(path); if path.is_absolute() { panic!("Only relative paths are allowed."); } let remove = self.remove_file(path); if remove.is_err() { panic!("Cannot remove file: {:?}", remove); } self } /// Prefix `path` with the current context of the DirBuilder fn path(&self, path: &str) -> PathBuf { let mut root = self.root.clone(); let path = PathBuf::from(path); root.push(path); root } /// Return the root path to the temporary directory fn root(&self) -> &Path { self.root.as_path() } } #[cfg(test)] mod tests { use super::*; #[test] fn test_testdir_temp_dir() { let path; { let dir = TestDir::temp(); // Dir created assert!(dir.root().exists()); let temp_dir = std::env::temp_dir(); // Dir inside system temp dir assert!(dir.root().starts_with(temp_dir)); path = dir.root().to_path_buf(); } // Dir deleted after out of scope assert!(!path.exists()); } #[test] fn test_testdir_current_rnd_dir() { let path; { let dir = TestDir::current_rnd(); // Dir created assert!(dir.root().exists()); let current_dir = std::env::current_dir().unwrap(); // Dir inside system temp dir assert!(dir.root().starts_with(current_dir)); path = dir.root().to_path_buf(); } // Dir deleted after out of scope assert!(!path.exists()); } #[test] fn test_testdir_current_dir() { let path; { let dir = TestDir::current("a/b/c"); // Dir created assert!(dir.root().exists()); let current_dir = std::env::current_dir().unwrap(); // Dir inside system temp dir assert!(dir.root().starts_with(current_dir)); path = dir.root().to_path_buf(); } // Dir deleted after out of scope assert!(!path.exists()); } #[test] fn test_testdir_path() { let str_path = "a/b/c/d/e"; let dir = TestDir::temp().create(str_path, FileType::Dir); let mut root = dir.root().to_path_buf(); let path = Path::new(str_path); root.push(path); assert_eq!(dir.path(str_path), root); assert!(dir.path(str_path).exists()); } #[test] fn test_testdir_create() { let dir = TestDir::temp(); let name = "dir"; let dir = dir.create(name, FileType::Dir); assert!(dir.path(name).exists()); assert!(dir.path(name).is_dir()); let name = "empty"; let dir = dir.create(name, FileType::EmptyFile); assert!(dir.path(name).exists()); assert!(dir.path(name).is_file()); assert_eq!(dir.path(name).metadata().unwrap().len(), 0); let name = "random"; let len = 1024; let dir = dir.create(name, FileType::RandomFile(len)); assert!(dir.path(name).exists()); assert!(dir.path(name).is_file()); assert_eq!(dir.path(name).metadata().unwrap().len(), len as u64); let name = "zero"; let len = 1024; let dir = dir.create(name, FileType::ZeroFile(len)); assert!(dir.path(name).exists()); assert!(dir.path(name).is_file()); assert_eq!(dir.path(name).metadata().unwrap().len(), len as u64); } #[test] fn test_testdir_remove() { let dir = TestDir::temp(); let name = "test_file"; let dir = dir.create(name, FileType::EmptyFile); assert!(dir.path(name).exists()); let dir = dir.remove(name); assert!(!dir.path(name).exists()); } }