#![cfg_attr(coverage_nightly, coverage(off))]
use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicU32, Ordering};
use crate::error::Result;
use crate::prelude::{Database, Ida};
pub fn with_db(f: impl FnOnce(&mut Database) -> Result<()> + Send + 'static) -> Result<()> {
let Some(source) = crate::corpus::canonical() else {
return Ok(());
};
let copy = WorkingCopy::of(&source);
let path = copy.path().to_owned();
Ida::run(move |ida| {
ida.call(move |db| {
db.open(&path).call()?;
let outcome = f(db);
db.close(false);
outcome
})
.unwrap_or_else(|e| e.resume())
})
.expect("doctest kernel bring-up failed")
}
struct WorkingCopy {
dir: PathBuf,
path: PathBuf,
}
static NEXT: AtomicU32 = AtomicU32::new(0);
impl WorkingCopy {
fn of(src: &Path) -> Self {
let unique = format!(
"idakit-doctest-{}-{}",
std::process::id(),
NEXT.fetch_add(1, Ordering::Relaxed)
);
let dir = scratch_root().join(unique);
std::fs::create_dir_all(&dir).expect("create scratch dir");
let file_name = src.file_name().expect("fixture has a file name");
let path = dir.join(file_name);
std::fs::copy(src, &path).expect("copy fixture into scratch");
Self { dir, path }
}
fn path(&self) -> &str {
self.path.to_str().expect("scratch path is valid UTF-8")
}
}
impl Drop for WorkingCopy {
fn drop(&mut self) {
let _ = std::fs::remove_dir_all(&self.dir);
}
}
fn scratch_root() -> PathBuf {
let shm = PathBuf::from("/dev/shm");
if shm.is_dir() {
return shm;
}
std::env::temp_dir()
}