use predicates::prelude::*;
mod common;
fn mount_line_count(ctx: &common::TestContext, box_id: &str) -> usize {
let output = ctx
.new_cmd()
.args(["exec", box_id, "--", "sh", "-c", "wc -l < /proc/mounts"])
.assert()
.success()
.get_output()
.clone();
String::from_utf8_lossy(&output.stdout)
.trim()
.parse::<usize>()
.expect("wc -l should print an integer")
}
#[test]
fn exec_does_not_grow_proc_mounts() {
let mut ctx = common::boxlite();
ctx.cmd.args(["run", "-d", "alpine:latest", "sleep", "300"]);
let output = ctx.cmd.assert().success().get_output().clone();
let box_id = String::from_utf8_lossy(&output.stdout).trim().to_string();
let baseline = mount_line_count(&ctx, &box_id);
assert!(
baseline > 0,
"baseline /proc/mounts line count should be positive, got {baseline}"
);
let mut counts = vec![baseline];
for _ in 0..5 {
counts.push(mount_line_count(&ctx, &box_id));
}
let max = *counts.iter().max().unwrap();
let min = *counts.iter().min().unwrap();
assert_eq!(
max, min,
"tenant exec must not change the container mount count; \
/proc/mounts line counts across execs were {counts:?} \
(growth here means libcontainer is re-applying ro/masked paths per exec)"
);
ctx.new_cmd()
.args(["rm", "--force", &box_id])
.assert()
.success()
.stdout(predicate::str::is_empty().or(predicate::str::contains(&box_id)));
}