use assert2::let_assert; use kxio::fs; type TestResult = Result<(), fs::Error>; mod path_of { use super::*; #[test] fn validate_fails_on_path_traversal() -> TestResult { let fs = fs::temp().expect("temp fs"); let_assert!(Err(fs::Error::PathTraversal { base, path: _path }) = fs.path_of("..".into())); assert_eq!(base, fs.base()); Ok(()) } #[test] fn matches_joins() -> TestResult { let fs = fs::temp().expect("temp fs"); let joined = fs.base().join("foo").join("bar"); let path_of = fs .path_of("foo/bar".into()) .expect("parse foo/bar into path"); assert_eq!(joined, path_of); Ok(()) } } mod path { use super::*; #[test] fn path_is_dir_as_dir_some() -> TestResult { let fs = fs::temp().expect("temp fs"); let path = fs.base().join("foo"); let dir = fs.dir(&path); dir.create().expect("create"); let_assert!(Ok(Some(as_dir)) = fs.path(&path).as_dir()); assert_eq!(dir.as_pathbuf(), as_dir.as_pathbuf()); Ok(()) } #[test] fn path_is_file_as_dir_none() -> TestResult { let fs = fs::temp().expect("temp fs"); let path = fs.base().join("foo"); let file = fs.file(&path); file.write("contents").expect("create"); let_assert!(Ok(Some(as_file)) = fs.path(&path).as_file()); assert_eq!(file.as_pathbuf(), as_file.as_pathbuf()); assert_eq!(as_file.reader().expect("reader").to_string(), "contents"); Ok(()) } #[test] fn path_is_dir_as_file_none() -> TestResult { let fs = fs::temp().expect("temp fs"); let path = fs.base().join("foo"); let dir = fs.dir(&path); dir.create().expect("create"); let_assert!(Ok(None) = fs.path(&path).as_file()); Ok(()) } #[test] fn path_is_file_as_file_some() -> TestResult { let fs = fs::temp().expect("temp fs"); let path = fs.base().join("foo"); let file = fs.file(&path); file.write("contents").expect("create"); let_assert!(Ok(None) = fs.path(&path).as_dir()); Ok(()) } } mod file { use super::*; #[test] /// Write to a file, read it, verify it exists, is a file and has the expected contents fn write_read_file_exists() -> TestResult { let fs = fs::temp().expect("temp fs"); let pathbuf = fs.base().join("foo"); let file = fs.file(&pathbuf); file.write("content").expect("write"); let c = file.reader().expect("reader").to_string(); assert_eq!(c, "content"); let path = fs.path(&pathbuf); let exists = path.exists().expect("exists"); assert!(exists); let is_file = path.is_file().expect("is_file"); assert!(is_file); Ok(()) } #[test] fn read_file_lines() -> TestResult { let fs = fs::temp().expect("temp fs"); let path = fs.base().join("foo"); let file = fs.file(&path); file.write("line 1\nline 2").expect("write"); let reader = file.reader().expect("reader"); let lines = reader.lines().collect::>(); assert_eq!(lines, vec!["line 1", "line 2"]); Ok(()) } } mod dir_create { use super::*; #[test] fn should_create_a_dir() -> TestResult { let fs = fs::temp().expect("temp fs"); let pathbuf = fs.base().join("subdir"); fs.dir(&pathbuf).create().expect("create"); let exists = fs.path(&pathbuf).exists().expect("exitss"); assert!(exists); let is_dir = fs.path(&pathbuf).is_dir().expect("is dir"); assert!(is_dir); Ok(()) } #[test] fn should_fail_on_path_traversal() -> TestResult { let fs = fs::temp().expect("temp fs"); let path = fs.base().join("..").join("foo"); let_assert!( Err(fs::Error::PathTraversal { base: _base, path: _path }) = fs.dir(&path).create() ); Ok(()) } } mod dir_create_all { use super::*; #[test] fn should_create_a_dir() -> TestResult { let fs = fs::temp().expect("temp fs"); let pathbuf = fs.base().join("subdir").join("child"); fs.dir(&pathbuf).create_all().expect("create_all"); let path = fs.path(&pathbuf); let exists = path.exists().expect("exists"); assert!(exists, "path exists"); let is_dir = path.is_dir().expect("is_dir"); assert!(is_dir, "path is a directory"); Ok(()) } #[test] fn should_fail_on_path_traversal() -> TestResult { let fs = fs::temp().expect("temp fs"); let path = fs.base().join("..").join("foo"); let_assert!( Err(fs::Error::PathTraversal { base: _base, path: _path }) = fs.dir(&path).create_all() ); Ok(()) } } mod dir_dir_read { use crate::fs::DirItem; use super::*; #[test] fn should_return_dir_items() -> TestResult { let fs = fs::temp().expect("temp fs"); let file1 = fs.base().join("file-1"); let dir = fs.base().join("dir"); let file2 = dir.join("file-2"); fs.file(&file1).write("file-1").expect("write: file-1"); fs.dir(&dir).create().expect("create dir"); fs.file(&file2).write("file-2").expect("write: file-2"); let items = fs .dir(fs.base()) .read() .expect("dir.read") .filter_map(|i| i.ok()) .collect::>(); assert_eq!(items.len(), 2); assert!(items.contains(&DirItem::File(file1))); assert!(items.contains(&DirItem::Dir(dir))); Ok(()) } #[test] fn should_fail_on_not_a_dir() -> TestResult { let fs = fs::temp().expect("temp fs"); let path = fs.base().join("file"); fs.file(&path).write("contents").expect("write"); let_assert!(Err(fs::Error::NotADirectory { path: _path }) = fs.dir(&path).read()); Ok(()) } #[test] fn should_fail_on_path_traversal() -> TestResult { let fs = fs::temp().expect("temp fs"); let path = fs.base().join("..").join("foo"); let_assert!( Err(fs::Error::PathTraversal { base: _base, path: _path }) = fs.dir(&path).read() ); Ok(()) } } mod dir_remove { use super::*; #[test] fn should_remove_a_dir() -> TestResult { let fs = fs::temp().expect("temp fs"); let path = fs.base().join("foo"); fs.dir(&path).create().expect("create"); fs.dir(&path).remove().expect("remove"); let exists = fs.path(&path).exists().expect("exists"); assert!(!exists); Ok(()) } #[test] fn should_fail_on_path_traversal() -> TestResult { let fs = fs::temp().expect("temp fs"); let path = fs.base().join("..").join("foo"); let_assert!( Err(fs::Error::PathTraversal { base: _base, path: _path }) = fs.dir(&path).remove() ); Ok(()) } } mod dir_remove_all { use super::*; #[test] fn should_remove_a_dir() -> TestResult { let fs = fs::temp().expect("temp fs"); let path = fs.base().join("foo"); let dir = fs.dir(&path); dir.create().expect("create dir"); let sub_path = path.join("sub"); let sub = fs.dir(&sub_path); sub.create().expect("create sub"); let file = sub_path.join("file"); fs.file(&file).write("contents").expect("write"); dir.remove_all().expect("remove"); let exists = dir.exists().expect("exists"); assert!(!exists); Ok(()) } #[test] fn should_fail_on_path_traversal() -> TestResult { let fs = fs::temp().expect("temp fs"); let path = fs.base().join("..").join("foo"); let_assert!( Err(fs::Error::PathTraversal { base: _base, path: _path }) = fs.dir(&path).remove_all() ); Ok(()) } } mod path_exists { use super::*; #[test] fn should_be_true_when_it_exists() -> TestResult { let fs = fs::temp().expect("temp fs"); let path = fs.base().join("foo"); fs.file(&path).write("bar").expect("write"); let exists = fs.path(&path).exists().expect("exists"); assert!(exists); Ok(()) } #[test] fn should_be_false_when_it_does_not_exist() -> TestResult { let fs = fs::temp().expect("temp fs"); let path = fs.base().join("foo"); let exists = fs.path(&path).exists().expect("exists"); assert!(!exists); Ok(()) } #[test] fn should_fail_on_path_traversal() -> TestResult { let fs = fs::temp().expect("temp fs"); let path = fs.base().join("..").join("foo"); let_assert!( Err(fs::Error::PathTraversal { base: _base, path: _path }) = fs.path(&path).exists() ); Ok(()) } } mod path_is_dir { use super::*; #[test] fn should_be_true_when_is_a_dir() -> TestResult { let fs = fs::temp().expect("temp fs"); let path = fs.base().join("foo"); fs.dir(&path).create().expect("create"); let is_dir = fs.path(&path).is_dir().expect("is_dir"); assert!(is_dir); Ok(()) } #[test] fn should_be_false_when_is_a_file() -> TestResult { let fs = fs::temp().expect("temp fs"); let path = fs.base().join("foo"); fs.file(&path).write("bar").expect("write"); let is_dir = fs.path(&path).is_dir().expect("is_dir"); assert!(!is_dir); Ok(()) } #[test] #[ignore] fn should_be_false_when_is_a_link() -> TestResult { let fs = fs::temp().expect("temp fs"); let path = fs.base().join("foo"); // TODO: (#38) create a link // let_assert!(Ok(_) = fs.file_write(&path, "bar")); let is_dir = fs.path(&path).is_dir().expect("is_dir"); assert!(!is_dir); Ok(()) } #[test] fn should_fail_on_path_traversal() -> TestResult { let fs = fs::temp().expect("temp fs"); let path = fs.base().join("..").join("foo"); let_assert!( Err(fs::Error::PathTraversal { base: _base, path: _path }) = fs.dir(&path).is_dir() ); Ok(()) } } mod path_is_file { use super::*; #[test] fn should_be_true_when_is_a_file() -> TestResult { let fs = fs::temp().expect("temp fs"); let path = fs.base().join("foo"); fs.file(&path).write("bar").expect("write"); let is_file = fs.path(&path).is_file().expect("is_file"); assert!(is_file); Ok(()) } #[test] fn should_be_false_when_is_a_dir() -> TestResult { let fs = fs::temp().expect("temp fs"); let path = fs.base().join("foo"); fs.dir(&path).create().expect("create"); let is_file = fs.path(&path).is_file().expect("is_file"); assert!(!is_file); Ok(()) } #[test] #[ignore] fn should_be_false_when_is_a_link() -> TestResult { let fs = fs::temp().expect("temp fs"); let path = fs.base().join("foo"); // TODO: (#38) create a link // let_assert!(Ok(_) = fs.file_write(&path, "bar")); let is_file = fs.path(&path).is_file().expect("is_file"); assert!(!is_file); Ok(()) } #[test] fn should_fail_on_path_traversal() -> TestResult { let fs = fs::temp().expect("temp fs"); let path = fs.base().join("..").join("foo"); let_assert!( Err(fs::Error::PathTraversal { base: _base, path: _path }) = fs.file(&path).is_file() ); Ok(()) } } mod copy { use super::*; #[test] fn should_copy_a_file() -> TestResult { let fs = fs::temp().expect("temp fs"); let src_path = fs.base().join("foo"); let src = fs.file(&src_path); src.write("bar").expect("write"); let dst_path = fs.base().join("bar"); let dst = fs.file(&dst_path); src.copy(&dst).expect("copy"); let src_contents = src.reader().expect("reader").to_string(); let dst_contents = dst.reader().expect("reader").to_string(); assert_eq!(src_contents, dst_contents); Ok(()) } } mod reader { use super::*; mod bytes { use super::*; #[test] fn should_return_bytes() -> TestResult { let fs = fs::temp().expect("temp fs"); let path = fs.base().join("foo"); let file = fs.file(&path); file.write("bar").expect("write"); let reader = file.reader().expect("reader"); let bytes = reader.bytes(); assert_eq!(bytes.len(), 3); assert_eq!(bytes[0], b'b'); assert_eq!(bytes[1], b'a'); assert_eq!(bytes[2], b'r'); Ok(()) } } }