use uuid::Uuid; use dodo::storage::{LockedDirectory, Storage}; /* * ================================================================== * ========================> PLEASE READ!!! <======================== * ================================================================== * * LockedDirectory is a wrapper around the Directory structure. * We only test the added lock feature. */ #[test] fn should_lock_new_entry() { let folder = fixture::create_folder(); let mut storage = LockedDirectory::new(&folder).expect("could not create storage"); let id = { let (id, _write) = storage.new().expect("could not create new entry"); fixture::assert_entry_locked_exclusive(&folder, id); id }; fixture::assert_entry_unlocked(&folder, id); } #[test] fn should_lock_while_reading_entry() { let folder = fixture::create_folder(); let id = Uuid::parse_str("78190929-3d84-4735-9e40-80e3cd5530e9").unwrap(); fixture::create_entry_in(&folder, id, "content"); let storage = LockedDirectory::new(&folder).expect("could not create storage"); { let _read = storage.read(id).expect("could not read entry"); fixture::assert_entry_locked_shared(&folder, id); }; fixture::assert_entry_unlocked(&folder, id); } #[test] fn should_lock_while_writing_entry() { let folder = fixture::create_folder(); let id = Uuid::parse_str("78190929-3d84-4735-9e40-80e3cd5530e9").unwrap(); let mut storage = LockedDirectory::new(&folder).expect("could not create storage"); { let _write = storage.write(id).expect("could not write to storage"); fixture::assert_entry_locked_exclusive(&folder, id); }; fixture::assert_entry_unlocked(&folder, id); } #[test] fn should_lock_while_overwriting_entry() { let folder = fixture::create_folder(); let id = Uuid::parse_str("78190929-3d84-4735-9e40-80e3cd5530e9").unwrap(); fixture::create_entry_in(&folder, id, "content"); let mut storage = LockedDirectory::new(&folder).expect("could not create storage"); { let _write = storage.overwrite(id).expect("could not write to storage"); fixture::assert_entry_locked_exclusive(&folder, id); }; fixture::assert_entry_unlocked(&folder, id); } mod fixture { use std::{fs::{self, File}, path::{Path, PathBuf}}; use fs2::{self, FileExt}; use uuid::Uuid; pub fn create_folder() -> tempfile::TempDir { tempfile::tempdir().expect("could not create folder") } pub fn create_file_in>(folder: P, name: &str, content: &str) -> PathBuf { let path = folder.as_ref().join(name); fs::write(&path, content).expect("could not create file"); path } pub fn create_entry_in>(folder: P, id: Uuid, content: &str) { create_file_in(folder, &id.to_string(), content); } pub fn assert_entry_locked_shared>(folder: P, id: Uuid) { let path = folder.as_ref().join(id.to_string()); let file = File::open(path).expect("entry does not exist"); assert!(file.try_lock_shared().is_ok(), "entry should be lockable"); assert_eq!(file.try_lock_exclusive().err().expect("entry should have been locked").kind(), fs2::lock_contended_error().kind(), "entry should have been locked"); } pub fn assert_entry_locked_exclusive>(folder: P, id: Uuid) { let path = folder.as_ref().join(id.to_string()); let file = File::open(path).expect("entry does not exist"); assert_eq!(file.try_lock_exclusive().err().expect("entry should have been locked").kind(), fs2::lock_contended_error().kind(), "entry should have been locked"); } pub fn assert_entry_unlocked>(folder: P, id: Uuid) { let path = folder.as_ref().join(id.to_string()); let file = File::open(path).expect("entry does not exist"); assert!(file.try_lock_exclusive().is_ok(), "entry should have been unlocked"); } }