use std::path::{Path, PathBuf};
use super::{MountPoint, is_fuse, mounts_under, parse_mountinfo_line, unescape_mountinfo};
#[test]
fn unescape_plain_path_is_unchanged() {
assert_eq!(unescape_mountinfo("/mnt/data"), "/mnt/data");
}
#[test]
fn unescape_space_octal() {
assert_eq!(unescape_mountinfo("/mnt/my\\040dir"), "/mnt/my dir");
}
#[test]
fn unescape_multiple_sequences() {
assert_eq!(unescape_mountinfo("a\\012b\\134c"), "a\nb\\c");
}
#[test]
fn unescape_incomplete_sequence_kept_verbatim() {
assert_eq!(unescape_mountinfo("a\\04b"), "a\\04b");
}
#[test]
fn unescape_backslash_at_end_kept_verbatim() {
assert_eq!(unescape_mountinfo("a\\"), "a\\");
}
fn make_mountinfo_line(mountpoint: &str, fstype: &str, source: &str) -> String {
format!("42 1 8:1 / {mountpoint} rw,relatime - {fstype} {source} rw")
}
#[test]
fn parse_basic_ext4_line() {
let line = make_mountinfo_line("/", "ext4", "/dev/sda1");
let mp = parse_mountinfo_line(&line).expect("should parse");
assert_eq!(mp.path, PathBuf::from("/"));
assert_eq!(mp.fstype, "ext4");
}
#[test]
fn parse_fuse_sshfs_line() {
let line = make_mountinfo_line("/mnt/remote", "fuse.sshfs", "user@host:/srv");
let mp = parse_mountinfo_line(&line).expect("should parse");
assert_eq!(mp.path, PathBuf::from("/mnt/remote"));
assert_eq!(mp.fstype, "fuse.sshfs");
}
#[test]
fn parse_line_with_optional_fields() {
let line = "42 1 8:1 / /mnt/x rw peer:123 shared:45 - tmpfs tmpfs rw";
let mp = parse_mountinfo_line(line).expect("should parse with optional fields");
assert_eq!(mp.path, PathBuf::from("/mnt/x"));
assert_eq!(mp.fstype, "tmpfs");
}
#[test]
fn parse_mountpoint_with_encoded_space() {
let line = make_mountinfo_line("/mnt/my\\040volume", "ext4", "/dev/sdb1");
let mp = parse_mountinfo_line(&line).expect("should parse");
assert_eq!(mp.path, PathBuf::from("/mnt/my volume"));
}
#[test]
fn parse_returns_none_for_malformed_line() {
assert!(parse_mountinfo_line("not a valid mountinfo line").is_none());
assert!(parse_mountinfo_line("").is_none());
}
#[test]
fn is_fuse_recognises_bare_fuse() {
assert!(is_fuse("fuse"));
}
#[test]
fn is_fuse_recognises_fuseblk() {
assert!(is_fuse("fuseblk"));
}
#[test]
fn is_fuse_recognises_prefixed_variants() {
assert!(is_fuse("fuse.sshfs"));
assert!(is_fuse("fuse.rclone"));
assert!(is_fuse("fuse.gvfsd-fuse"));
}
#[test]
fn is_fuse_rejects_non_fuse() {
assert!(!is_fuse("ext4"));
assert!(!is_fuse("tmpfs"));
assert!(!is_fuse("btrfs"));
assert!(!is_fuse("nfs"));
}
#[test]
fn mounts_under_nonexistent_path_returns_empty() {
let result = mounts_under(Path::new("/this/path/does/not/exist/obliterate-test"));
assert!(result.is_ok());
assert!(result.unwrap().is_empty());
}
#[test]
fn mounts_under_returns_deepest_first() {
let mut mounts = vec![
MountPoint { path: PathBuf::from("/a"), fstype: "ext4".into()},
MountPoint { path: PathBuf::from("/a/b/c"), fstype: "tmpfs".into()},
MountPoint { path: PathBuf::from("/a/b"), fstype: "ext4".into()},
];
mounts.sort_by(|a, b| b.path.as_os_str().len().cmp(&a.path.as_os_str().len()));
assert_eq!(mounts[0].path, PathBuf::from("/a/b/c"));
assert_eq!(mounts[1].path, PathBuf::from("/a/b"));
assert_eq!(mounts[2].path, PathBuf::from("/a"));
}