use std::ffi::OsString;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use crate::*;
#[test]
fn test_new_default_types() {
let abs = PavedPath::new_absolute();
assert!(abs.is_absolute());
assert!(!abs.is_relative());
assert_eq!(abs.get_type(), PathType::Absolute);
let rel = PavedPath::new_relative();
assert!(rel.is_relative());
assert!(!rel.is_absolute());
assert_eq!(rel.get_type(), PathType::Relative);
}
#[test]
fn test_push_and_get_dirs() {
let path = PavedPath::new_relative()
.with_dir("a")
.with_dir("b")
.with_dir("c");
let dirs = path.get_dirs();
assert_eq!(dirs.len(), 3);
assert_eq!(dirs[0], "a");
assert_eq!(dirs[2], "c");
}
#[test]
fn test_push_dir_normalization() {
let path = PavedPath::new_relative()
.with_dir("a/b")
.with_dir(".")
.with_dir("..")
.with_dir("c");
let dirs = path.get_dirs();
assert_eq!(dirs, &[OsString::from("a"), OsString::from("c")]);
}
#[test]
fn test_file_handling() {
let path = PavedPath::new_relative()
.with_dir("foo")
.with_file("bar.txt");
assert!(path.has_file());
assert_eq!(path.get_file(), Some(&OsString::from("bar.txt")));
let no_file = path.clone().without_file();
assert!(!no_file.has_file());
assert_eq!(no_file.get_file(), None);
}
#[test]
fn test_path_in_style_unix() {
let path = PavedPath::new_absolute()
.with_dir("usr")
.with_dir("bin")
.with_file("bash");
let unix_path = path.path_in_style(PlatformStyle::Unix);
assert_eq!(unix_path, Path::new("/usr/bin/bash"));
}
#[test]
fn test_path_in_style_windows() {
let path = PavedPath::new_absolute()
.with_prefix(PathPrefix::Drive('C'))
.with_dir("Users")
.with_dir("Test")
.with_file("file.txt");
let win_path = path.path_in_style(PlatformStyle::Windows);
let s = win_path.to_string_lossy();
assert!(
s.starts_with("C:\\") || s.starts_with("C:/"),
"unexpected prefix: {s}"
);
assert!(s.ends_with("file.txt"));
}
#[test]
fn test_remove_prefix() {
let path = PavedPath::new_absolute()
.with_prefix(PathPrefix::Drive('D'))
.without_prefix();
assert!(path.get_prefix().is_none());
}
#[test]
fn test_pop_last_dir() {
let mut path = PavedPath::new_relative().with_dir("one").with_dir("two");
let last = path.pop_dir();
assert_eq!(last, Some(OsString::from("two")));
assert_eq!(path.last(), Some(&OsString::from("one")));
}
#[test]
fn test_conversion_from_and_to_path() {
let std_path = PathBuf::from("/usr/local/bin/bash");
let paved = PavedPath::from(std_path.clone());
assert!(paved.is_absolute());
assert_eq!(paved.get_file(), Some(&OsString::from("bash")));
assert_eq!(
paved.get_dirs(),
&vec![
OsString::from("usr"),
OsString::from("local"),
OsString::from("bin")
]
);
let unix_path = paved.path_in_style(PlatformStyle::Unix);
assert_eq!(unix_path, std_path);
let unix_string = unix_path.to_string_lossy().to_string();
assert_eq!(unix_string, "/usr/local/bin/bash");
}
#[test]
fn test_from_dirs_path_moves_file_to_dir() {
let original = PavedPath::from(Path::new("foo/bar/baz.txt"));
let dirs_only = PavedPath::from_dirs_path("foo/bar/baz.txt");
assert!(dirs_only.get_file().is_none());
assert_eq!(
dirs_only.get_dirs(),
&vec![
OsString::from("foo"),
OsString::from("bar"),
OsString::from("baz.txt")
]
);
assert_ne!(original.get_dirs(), dirs_only.get_dirs());
}
#[test]
fn test_add_and_add_assign() {
let left = PavedPath::new_relative().with_dir("a").with_dir("b");
let right = PavedPath::new_relative().with_dir("c").with_file("d.txt");
let combined = left.clone() + right.clone();
assert_eq!(
combined.get_dirs(),
&vec![
OsString::from("a"),
OsString::from("b"),
OsString::from("c")
]
);
assert_eq!(combined.get_file(), Some(&OsString::from("d.txt")));
let mut left_mut = left.clone();
left_mut += right;
assert_eq!(
left_mut.get_dirs(),
&vec![
OsString::from("a"),
OsString::from("b"),
OsString::from("c")
]
);
assert_eq!(left_mut.get_file(), Some(&OsString::from("d.txt")));
}
#[test]
fn test_extend_trait() {
let mut path = PavedPath::new_relative().with_dir("a");
path.extend(["b", "c", "d"]);
assert_eq!(
path.get_dirs(),
&vec![
OsString::from("a"),
OsString::from("b"),
OsString::from("c"),
OsString::from("d")
]
);
}
#[test]
fn test_from_string_and_str() {
let p1 = PavedPath::from("/tmp/test.txt".to_string());
let p2 = PavedPath::from_str("/tmp/test.txt").unwrap();
let unix1 = p1.path_in_style(PlatformStyle::Unix);
let unix2 = p2.path_in_style(PlatformStyle::Unix);
assert_eq!(unix1, unix2);
assert_eq!(p1.get_file(), Some(&OsString::from("test.txt")));
}
#[test]
fn test_into_iterator_combines_dirs_and_file() {
let path = PavedPath::new_relative()
.with_dir("foo")
.with_dir("bar")
.with_file("baz.txt");
let parts: Vec<_> = path.into_iter().collect();
assert_eq!(
parts,
vec![
OsString::from("foo"),
OsString::from("bar"),
OsString::from("baz.txt")
]
);
}
#[test]
fn absolutize_combines_root_and_relative() {
let root = PavedPath::from("/usr/local/");
let rel = PavedPath::from("bin/test");
let result = rel.absolutize(&root).expect("should succeed");
assert!(result.is_absolute());
assert_eq!(
result.build_unix_pathbuf(),
Path::new("/usr/local/bin/test")
);
assert_eq!(
result.build_windows_pathbuf(),
Path::new(r"\usr\local\bin\test")
);
}
#[test]
fn absolutize_fails_if_self_is_already_absolute() {
let root = PavedPath::from("/usr");
let already_abs = PavedPath::from("/bin");
let err = already_abs.absolutize(&root).expect_err("should fail");
assert_eq!(err, PavedAbsolutizeError::PathIsAbsolute);
}
#[test]
fn absolutize_fails_if_root_is_relative() {
let root = PavedPath::from("relative/root");
let rel = PavedPath::from("child/path");
let err = rel.absolutize(&root).expect_err("should fail");
assert_eq!(err, PavedAbsolutizeError::RootIsRelative);
}
#[test]
fn absolutize_preserves_windows_drive_prefix() {
let root = PavedPath::new_absolute()
.with_prefix(PathPrefix::Drive('C'))
.with_dir("Program Files")
.with_dir("MyApp");
let rel = PavedPath::from("data/config.ini");
let result = rel.absolutize(&root).expect("should succeed");
assert!(result.is_absolute());
assert_eq!(
result.build_windows_pathbuf(),
Path::new("C:\\Program Files\\MyApp\\data\\config.ini")
);
}
#[test]
fn test_set_dirs() {
let mut paved = PavedPath::from("/a/b/c/");
paved.set_dirs(["d", "e"]);
assert_eq!(paved.build_unix_pathbuf(), Path::new("/d/e/"));
}