use fs_ext4::block_io::FileDevice;
use fs_ext4::Filesystem;
use std::fs;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
#[track_caller]
fn image_path(name: &str) -> String {
fs_ext4_test_support::fixture(env!("CARGO_MANIFEST_DIR"), name)
}
#[track_caller]
fn copy_to_tmp(name: &str, tag: &str) -> String {
static COUNTER: AtomicUsize = AtomicUsize::new(0);
let n = COUNTER.fetch_add(1, Ordering::Relaxed);
let src = image_path(name);
let dst = fs_ext4_test_support::temp_path!("fs_ext4_orph_{}_{tag}_{n}.img", std::process::id());
fs::copy(&src, &dst).unwrap_or_else(|e| panic!("copy {src} -> {dst}: {e}"));
dst
}
#[test]
fn clean_image_reports_empty_orphan_list() {
let path = copy_to_tmp("ext4-basic.img", "clean");
let dev = FileDevice::open(&path).expect("ro");
let fs = Filesystem::mount(Arc::new(dev)).expect("mount");
let orphans = fs.orphan_list().expect("orphan_list");
assert!(
orphans.is_empty(),
"fresh fixture should have no orphans, got {orphans:?}"
);
assert_eq!(
fs.sb.last_orphan, 0,
"fresh fixture's s_last_orphan must be 0"
);
fs::remove_file(path).ok();
}
#[test]
fn orphan_list_does_not_panic_on_any_image() {
for img in &[
"ext4-basic.img",
"ext4-htree.img",
"ext4-largedir.img",
"ext4-deep-extents.img",
"ext4-inline.img",
"ext4-no-csum.img",
] {
let path = copy_to_tmp(img, "noprobe");
let result = std::panic::catch_unwind(|| {
let dev = FileDevice::open(&path).expect("ro");
let fs = Filesystem::mount(Arc::new(dev)).expect("mount");
let _ = fs.orphan_list();
});
assert!(result.is_ok(), "orphan_list panicked on {img}");
fs::remove_file(path).ok();
}
}