use std::fs::{File, OpenOptions};
use std::os::windows::fs::OpenOptionsExt;
use std::path::{Path, PathBuf};
use std::sync::{OnceLock, RwLock};
use windows_sys::Win32::Storage::FileSystem::FILE_FLAG_BACKUP_SEMANTICS;
pub(crate) fn handle_allocation() -> &'static RwLock<()> {
static LOCK: OnceLock<RwLock<()>> = OnceLock::new();
LOCK.get_or_init(|| RwLock::new(()))
}
pub(crate) struct Fixture {
directory: PathBuf,
}
pub(crate) const FILE_CONTENTS: &[u8] = b"contents";
impl Fixture {
pub(crate) fn new(label: &str) -> Self {
let directory = std::env::temp_dir().join(format!(
"windows-namespace-request-sys-{}-{label}",
std::process::id()
));
let _ = std::fs::remove_dir_all(&directory);
std::fs::create_dir_all(&directory).expect("create the fixture directory");
std::fs::write(directory.join("f.t"), FILE_CONTENTS).expect("write the fixture file");
Self { directory }
}
pub(crate) fn with_extra_files(label: &str, extra: usize) -> Self {
let fixture = Self::new(label);
for index in 0..extra {
std::fs::write(
fixture.directory.join(format!("e{index:03}.t")),
FILE_CONTENTS,
)
.expect("write an extra fixture file");
}
fixture
}
pub(crate) fn directory(&self) -> &Path {
&self.directory
}
pub(crate) fn file(&self) -> PathBuf {
self.directory.join("f.t")
}
pub(crate) fn open_file(&self) -> File {
File::open(self.file()).expect("open the fixture file")
}
pub(crate) fn open_directory(&self) -> File {
OpenOptions::new()
.read(true)
.custom_flags(FILE_FLAG_BACKUP_SEMANTICS)
.open(self.directory())
.expect("open the fixture directory")
}
}
impl Drop for Fixture {
fn drop(&mut self) {
let _ = std::fs::remove_dir_all(&self.directory);
}
}