use crate::soft_canonicalize;
use std::fs;
use std::path::Path;
use std::sync::Mutex;
use tempfile::tempdir;
static WORKING_DIR_MUTEX: Mutex<()> = Mutex::new(());
#[test]
fn test_relative_path_with_traversal() -> std::io::Result<()> {
let _lock = WORKING_DIR_MUTEX.lock().unwrap();
let current_dir = std::env::current_dir()?;
let expected = fs::canonicalize(current_dir)?.join("part");
let result = soft_canonicalize(Path::new("non/existing/../../part"))?;
#[cfg(not(feature = "dunce"))]
{
assert_eq!(result, expected, "Without dunce: exact match");
}
#[cfg(feature = "dunce")]
{
#[cfg(windows)]
{
let result_str = result.to_string_lossy();
let expected_str = expected.to_string_lossy();
assert!(!result_str.starts_with(r"\\?\"), "dunce should simplify");
assert!(
expected_str.starts_with(r"\\?\"),
"expected has UNC from std"
);
}
#[cfg(not(windows))]
{
assert_eq!(result, expected);
}
}
Ok(())
}
#[test]
fn test_mixed_existing_and_nonexisting_with_traversal() -> std::io::Result<()> {
let temp_dir = tempdir()?;
let existing_dir = temp_dir.path().join("existing");
fs::create_dir(&existing_dir)?;
let test_path = existing_dir
.join("nonexisting")
.join("..")
.join("sibling.txt");
let result = soft_canonicalize(test_path)?;
let expected = fs::canonicalize(&existing_dir)?.join("sibling.txt");
#[cfg(not(feature = "dunce"))]
{
assert_eq!(result, expected, "Without dunce: exact match");
}
#[cfg(feature = "dunce")]
{
#[cfg(windows)]
{
let result_str = result.to_string_lossy();
let expected_str = expected.to_string_lossy();
assert!(!result_str.starts_with(r"\\?\"), "dunce should simplify");
assert!(
expected_str.starts_with(r"\\?\"),
"expected has UNC from std"
);
}
#[cfg(not(windows))]
{
assert_eq!(result, expected);
}
}
Ok(())
}
#[test]
fn test_traversal_beyond_root() -> std::io::Result<()> {
let temp_dir = tempdir()?;
let test_path = temp_dir
.path()
.join("../../../../../../../../../root_file.txt");
let result = soft_canonicalize(test_path)?;
assert!(result.is_absolute());
assert!(!result.starts_with(temp_dir.path()));
Ok(())
}