use uuid::Uuid;
use dodo::storage::{LockedDirectory, Storage};
#[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<P: AsRef<Path>>(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<P: AsRef<Path>>(folder: P, id: Uuid, content: &str) {
create_file_in(folder, &id.to_string(), content);
}
pub fn assert_entry_locked_shared<P: AsRef<Path>>(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<P: AsRef<Path>>(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<P: AsRef<Path>>(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");
}
}