use super::load_user_patterns;
use crate::pattern::is_pattern_file;
use std::ffi::CString;
use std::os::unix::ffi::OsStrExt;
use std::os::unix::fs::symlink;
use std::path::Path;
use tempfile::TempDir;
const VALID_TOML: &str = "command_match = \"^valid\"\n";
fn make_fifo(path: &Path) {
let c_path = CString::new(path.as_os_str().as_bytes()).expect("path has no interior NUL");
let rc = unsafe { libc::mkfifo(c_path.as_ptr(), 0o600) };
if rc == 0 {
return;
}
let err = std::io::Error::last_os_error();
let parent = path.parent().unwrap_or(Path::new("."));
let parent_state = match std::fs::metadata(parent) {
Ok(m) if m.is_dir() => "is a directory".to_string(),
Ok(_) => "is not a directory".to_string(),
Err(e) => format!("metadata failed: {e}"),
};
let listing = match std::fs::read_dir(parent) {
Ok(entries) => entries
.filter_map(Result::ok)
.map(|e| e.file_name().to_string_lossy().into_owned())
.collect::<Vec<_>>()
.join(", "),
Err(e) => format!("read_dir failed: {e}"),
};
panic!(
"mkfifo({}) failed: {err}; parent {} {parent_state}; parent listing=[{listing}]",
path.display(),
parent.display(),
);
}
fn create_strays(dir: &Path) {
make_fifo(&dir.join("stray-fifo.toml"));
let sub = dir.join("stray-dir.toml");
std::fs::create_dir(&sub).unwrap();
let link = dir.join("stray-dangling.toml");
symlink(dir.join("missing-target.toml"), &link).unwrap();
}
#[test]
fn is_pattern_file_classifies_regular_and_nonregular_entries() {
let dir = TempDir::new().unwrap();
let path = dir.path().to_path_buf();
let regular = path.join("regular.toml");
std::fs::write(®ular, VALID_TOML).unwrap();
assert!(is_pattern_file(®ular).unwrap(), "regular file");
let target = path.join("target.txt");
std::fs::write(&target, "not toml").unwrap();
let to_regular = path.join("symlink-to-regular.toml");
symlink(&target, &to_regular).unwrap();
assert!(is_pattern_file(&to_regular).unwrap(), "symlink to regular");
let fifo = path.join("fifo.toml");
make_fifo(&fifo);
assert!(!is_pattern_file(&fifo).unwrap(), "fifo");
let subdir = path.join("subdir.toml");
std::fs::create_dir(&subdir).unwrap();
assert!(!is_pattern_file(&subdir).unwrap(), "directory");
let dangling = path.join("dangling.toml");
symlink(path.join("missing.toml"), &dangling).unwrap();
assert!(!is_pattern_file(&dangling).unwrap(), "dangling symlink");
let loop_link = path.join("loop.toml");
symlink(&loop_link, &loop_link).unwrap();
assert!(
is_pattern_file(&loop_link).is_err(),
"symlink loop must be an Err, not a skip"
);
}
#[test]
fn load_user_patterns_skips_nonregular_entries() {
let dir = TempDir::new().unwrap();
let path = dir.path().to_path_buf();
std::fs::write(path.join("valid.toml"), VALID_TOML).unwrap();
create_strays(&path);
let patterns = load_user_patterns(dir.path());
assert_eq!(patterns.len(), 1, "expected exactly one pattern");
assert_eq!(patterns[0].command_match.as_str(), "^valid");
}
#[test]
fn load_user_patterns_ignores_invalid_toml_content() {
let dir = TempDir::new().unwrap();
std::fs::write(dir.path().join("good.toml"), VALID_TOML).unwrap();
std::fs::write(dir.path().join("bad.toml"), "not toml =").unwrap();
let patterns = load_user_patterns(dir.path());
assert_eq!(patterns.len(), 1);
}