Watch
0
0
Fork
You've already forked hyperhive
0

tests use mockall for expectation-style doubles, starting with the builder and hive-priv seams

This commit is contained in:
atlas 2026-11-03 13:58:43 +01:00
commit b0a6a28d10
2 changed files with 182 additions and 59 deletions

View file

@ -16,3 +16,6 @@ serde_json.workspace = true
tokio.workspace = true
tracing.workspace = true
tracing-subscriber.workspace = true
[dev-dependencies]
mockall.workspace = true

View file

@ -179,6 +179,7 @@ fn is_subvolume_root(on_btrfs: bool, ino: Option<u64>) -> bool {
/// The two questions the storage ops ask the state filesystem. [`RealProbes`]
/// is production; tests answer without a btrfs filesystem.
#[cfg_attr(test, mockall::automock)]
trait Probes {
/// Whether `path` lives on a btrfs filesystem; an error when it cannot be
/// told.
@ -1009,7 +1010,7 @@ async fn set_subvolume_quota(
#[cfg(test)]
mod tests {
use super::{
Command, Env, Probes, agent_disk_paths, cleanup_stale_path, delete_agent_snapshot,
Command, Env, MockProbes, agent_disk_paths, cleanup_stale_path, delete_agent_snapshot,
delete_agent_subvolume, du_command, du_total, ensure_agent_subvolume,
ensure_btrfs_quota_in, exec_delete_agent_snapshot, exec_delete_agent_subvolume,
exec_ensure_agent_subvolume, exec_measure_agent_disk, exec_read_subvolume_usage,
@ -1412,21 +1413,31 @@ mod tests {
.collect()
}
/// An [`Env`] over this tree, running `btrfs` and the two probes given.
/// An [`Env`] over this tree, running `btrfs` and probes that answer
/// with the functions given.
fn env<'a, S: Spawn>(
&'a self,
spawn: &'a S,
on_btrfs: fn(&Path) -> anyhow::Result<bool>,
is_subvolume: fn(&Path) -> bool,
) -> Env<'a, &'a S, FnProbes> {
) -> Env<'a, &'a S, MockProbes> {
let mut probes = MockProbes::new();
probes.expect_on_btrfs().returning(on_btrfs);
probes.expect_is_subvolume().returning(is_subvolume);
self.env_with(spawn, probes)
}
/// An [`Env`] over this tree, running `btrfs` and the `probes` given.
fn env_with<'a, S: Spawn>(
&'a self,
spawn: &'a S,
probes: MockProbes,
) -> Env<'a, &'a S, MockProbes> {
Env {
state_root: &self.state,
staging_root: &self.staging,
spawn,
probes: FnProbes {
on_btrfs,
is_subvolume,
},
probes,
}
}
@ -1440,22 +1451,6 @@ mod tests {
}
}
/// Probes answered by the functions given.
struct FnProbes {
on_btrfs: fn(&Path) -> anyhow::Result<bool>,
is_subvolume: fn(&Path) -> bool,
}
impl Probes for FnProbes {
fn on_btrfs(&self, path: &Path) -> anyhow::Result<bool> {
(self.on_btrfs)(path)
}
fn is_subvolume(&self, path: &Path) -> bool {
(self.is_subvolume)(path)
}
}
/// Creates, deletes and snapshots as btrfs does; `send` writes `STREAM`.
const LIKE_BTRFS: &str = r#"case "$1 $2" in
"subvolume create") mkdir "$3";;
@ -1490,7 +1485,8 @@ esac"#;
let fx = Fx::new();
std::fs::create_dir(fx.agent("iris")).unwrap();
let btrfs = fx.btrfs(LIKE_BTRFS);
let env = fx.env(&btrfs, on_btrfs, not_subvol);
// No expectation is set: a probe call would panic.
let env = fx.env_with(&btrfs, MockProbes::new());
assert_eq!(
ensure_agent_subvolume(&env, "iris").await.unwrap(),
(String::new(), String::new())