use crate::types::plan::Plan;
#[derive(Debug, Copy, Clone)]
pub struct SmokeFailure;
pub trait SmokeTestRunner: Send + Sync {
fn run(&self, plan: &Plan) -> Result<(), SmokeFailure>;
}
#[derive(Debug, Default, Copy, Clone)]
pub struct DefaultSmokeRunner;
impl SmokeTestRunner for DefaultSmokeRunner {
fn run(&self, plan: &Plan) -> Result<(), SmokeFailure> {
for act in &plan.actions {
if let crate::types::Action::EnsureSymlink { source, target } = act {
let Ok(md) = std::fs::symlink_metadata(target.as_path()) else {
return Err(SmokeFailure);
};
if !md.file_type().is_symlink() {
return Err(SmokeFailure);
}
let Ok(link) = std::fs::read_link(target.as_path()) else {
return Err(SmokeFailure);
};
let resolved = if link.is_relative() {
match target.as_path().parent() {
Some(parent) => parent.join(link),
None => link,
}
} else {
link
};
let want = std::fs::canonicalize(source.as_path())
.unwrap_or_else(|_| source.as_path().clone());
let got = std::fs::canonicalize(&resolved).unwrap_or(resolved);
if want != got {
return Err(SmokeFailure);
}
}
}
Ok(())
}
}