aboutsummaryrefslogtreecommitdiff
path: root/helix-stdx/tests
diff options
context:
space:
mode:
authorMichael Davis2024-01-16 18:59:48 +0000
committerBlaž Hrastnik2024-01-18 01:57:53 +0000
commit1f916e65cff4459698d465b2f4558da1e1bf6e44 (patch)
tree5b6768e3069085bc5ba995efa95fdc73241ed0f6 /helix-stdx/tests
parentaf8e524a7d06253fa854bf8954f64312e11d0ea0 (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.rs124
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(())
+}