6b863d2d2d
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
60 lines
2.1 KiB
Rust
60 lines
2.1 KiB
Rust
//! The vault lock file (SPEC §4.2).
|
|
|
|
mod common;
|
|
|
|
use std::fs;
|
|
|
|
use notescraft_vault::{Error, Vault};
|
|
|
|
/// A pid no live process can have on Linux or macOS.
|
|
const DEAD_PID: u32 = 4_294_967_294;
|
|
|
|
#[test]
|
|
fn opening_creates_the_private_state_folder_and_the_lock() {
|
|
let (dir, vault) = common::vault("lock");
|
|
let lock = dir.path().join(".notescraft/lock");
|
|
assert!(vault.root().is_dir());
|
|
assert!(lock.is_file());
|
|
let content = fs::read_to_string(&lock).unwrap();
|
|
assert_eq!(content.split_whitespace().next().unwrap(), std::process::id().to_string());
|
|
assert_eq!(vault.root(), fs::canonicalize(dir.path()).unwrap());
|
|
}
|
|
|
|
#[test]
|
|
fn a_second_instance_is_locked_out() {
|
|
let (dir, _vault) = common::vault("locked");
|
|
let err = Vault::open(dir.path()).expect_err("second writer");
|
|
assert!(matches!(err, Error::Locked { pid } if pid == std::process::id()), "{err:?}");
|
|
}
|
|
|
|
#[test]
|
|
fn a_lock_owned_by_a_dead_process_is_taken_over() {
|
|
let dir = common::TempDir::new("takeover");
|
|
fs::create_dir_all(dir.path().join(".notescraft")).unwrap();
|
|
fs::write(dir.path().join(".notescraft/lock"), format!("{DEAD_PID} 1700000000")).unwrap();
|
|
|
|
let vault = Vault::open(dir.path()).expect("stale lock must be taken over");
|
|
let content = fs::read_to_string(dir.path().join(".notescraft/lock")).unwrap();
|
|
assert_eq!(content.split_whitespace().next().unwrap(), std::process::id().to_string());
|
|
drop(vault);
|
|
}
|
|
|
|
#[test]
|
|
fn dropping_the_vault_releases_the_lock() {
|
|
let dir = common::TempDir::new("release");
|
|
drop(Vault::open(dir.path()).unwrap());
|
|
assert!(!dir.path().join(".notescraft/lock").exists());
|
|
// The lock is free again, and a second take-over works.
|
|
drop(Vault::open(dir.path()).expect("lock released"));
|
|
}
|
|
|
|
#[test]
|
|
fn read_only_open_does_not_take_the_lock() {
|
|
let dir = common::TempDir::new("ro-lock");
|
|
let read_only = Vault::open_read_only(dir.path()).unwrap();
|
|
assert!(!dir.path().join(".notescraft/lock").exists());
|
|
let writer = Vault::open(dir.path()).expect("read-only opens leave the lock free");
|
|
assert!(writer.root().is_dir());
|
|
drop(read_only);
|
|
}
|