diff options
author | Michael Davis | 2024-01-16 18:59:48 +0000 |
---|---|---|
committer | Blaž Hrastnik | 2024-01-18 01:57:53 +0000 |
commit | 1f916e65cff4459698d465b2f4558da1e1bf6e44 (patch) | |
tree | 5b6768e3069085bc5ba995efa95fdc73241ed0f6 /helix-stdx/tests | |
parent | af8e524a7d06253fa854bf8954f64312e11d0ea0 (diff) |
Create helix-stdx crate for stdlib extensions
helix-stdx is meant to carry extensions to the stdlib or low-level
dependencies that are useful in all other crates. This commit starts
with all of the path functions from helix-core and the CWD tracking that
lived in helix-loader.
The CWD tracking in helix-loader was previously unable to call the
canonicalization functions in helix-core. Switching to our custom
canonicalization code should make no noticeable difference though
since `std::env::current_dir` returns a canonicalized path with
symlinks resolved (at least on unix).
Diffstat (limited to 'helix-stdx/tests')
-rw-r--r-- | helix-stdx/tests/path.rs | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/helix-stdx/tests/path.rs b/helix-stdx/tests/path.rs new file mode 100644 index 00000000..cc3c15cb --- /dev/null +++ b/helix-stdx/tests/path.rs @@ -0,0 +1,124 @@ +#![cfg(windows)] + +use std::{ + env::set_current_dir, + error::Error, + path::{Component, Path, PathBuf}, +}; + +use helix_stdx::path; +use tempfile::Builder; + +// Paths on Windows are almost always case-insensitive. +// Normalization should return the original path. +// E.g. mkdir `CaSe`, normalize(`case`) = `CaSe`. +#[test] +fn test_case_folding_windows() -> Result<(), Box<dyn Error>> { + // tmp/root/case + let tmp_prefix = std::env::temp_dir(); + set_current_dir(&tmp_prefix)?; + + let root = Builder::new().prefix("root-").tempdir()?; + let case = Builder::new().prefix("CaSe-").tempdir_in(&root)?; + + let root_without_prefix = root.path().strip_prefix(&tmp_prefix)?; + + let lowercase_case = format!( + "case-{}", + case.path() + .file_name() + .unwrap() + .to_string_lossy() + .split_at(5) + .1 + ); + let test_path = root_without_prefix.join(lowercase_case); + assert_eq!( + path::normalize(&test_path), + case.path().strip_prefix(&tmp_prefix)? + ); + + Ok(()) +} + +#[test] +fn test_normalize_path() -> Result<(), Box<dyn Error>> { + /* + tmp/root/ + ├── link -> dir1/orig_file + ├── dir1/ + │ └── orig_file + └── dir2/ + └── dir_link -> ../dir1/ + */ + + let tmp_prefix = std::env::temp_dir(); + set_current_dir(&tmp_prefix)?; + + // Create a tree structure as shown above + let root = Builder::new().prefix("root-").tempdir()?; + let dir1 = Builder::new().prefix("dir1-").tempdir_in(&root)?; + let orig_file = Builder::new().prefix("orig_file-").tempfile_in(&dir1)?; + let dir2 = Builder::new().prefix("dir2-").tempdir_in(&root)?; + + // Create path and delete existing file + let dir_link = Builder::new() + .prefix("dir_link-") + .tempfile_in(&dir2)? + .path() + .to_owned(); + let link = Builder::new() + .prefix("link-") + .tempfile_in(&root)? + .path() + .to_owned(); + + use std::os::windows; + windows::fs::symlink_dir(&dir1, &dir_link)?; + windows::fs::symlink_file(&orig_file, &link)?; + + // root/link + let path = link.strip_prefix(&tmp_prefix)?; + assert_eq!( + path::normalize(path), + path, + "input {:?} and symlink last component shouldn't be resolved", + path + ); + + // root/dir2/dir_link/orig_file/../.. + let path = dir_link + .strip_prefix(&tmp_prefix) + .unwrap() + .join(orig_file.path().file_name().unwrap()) + .join(Component::ParentDir) + .join(Component::ParentDir); + let expected = dir_link + .strip_prefix(&tmp_prefix) + .unwrap() + .join(Component::ParentDir); + assert_eq!( + path::normalize(&path), + expected, + "input {:?} and \"..\" should not erase the simlink that goes ahead", + &path + ); + + // root/link/.././../dir2/../ + let path = link + .strip_prefix(&tmp_prefix) + .unwrap() + .join(Component::ParentDir) + .join(Component::CurDir) + .join(Component::ParentDir) + .join(dir2.path().file_name().unwrap()) + .join(Component::ParentDir); + let expected = link + .strip_prefix(&tmp_prefix) + .unwrap() + .join(Component::ParentDir) + .join(Component::ParentDir); + assert_eq!(path::normalize(&path), expected, "input {:?}", &path); + + Ok(()) +} |