169 lines · 5.2 KB · Rust
RawDownload
use std::{    path::{Path, PathBuf},    time::Duration,}; use bstr::ByteVec;use gix_path::{realpath::Error, realpath_opts};use gix_testtools::tempfile; #[test]fn fuzzed_timeout() -> crate::Result {    let path = PathBuf::from(std::fs::read("tests/fixtures/fuzzed/54k-path-components.path")?.into_string()?);    assert_eq!(path.components().count(), 54862);    let start = std::time::Instant::now();    assert!(matches!(        gix_path::realpath_opts(&path, Path::new("/cwd"), gix_path::realpath::MAX_SYMLINKS).unwrap_err(),        gix_path::realpath::Error::ExcessiveComponentCount {            max_symlink_checks: 2048        }    ));    assert!(        start.elapsed() < Duration::from_millis(if cfg!(windows) { 2000 } else { 500 }),        "took too long: {:.02} , we can't take too much time for this, and should keep the amount of work reasonable\        as paths can be part of URls which sometimes are canonicalized",        start.elapsed().as_secs_f32()    );    Ok(())} #[test]fn assorted() -> crate::Result {    let cwd = tempfile::tempdir()?;    let cwd = cwd.path();    let symlinks_disabled = 0;     assert!(        matches!(            realpath_opts("".as_ref(), cwd, symlinks_disabled),            Err(Error::EmptyPath)        ),        "Empty path is not allowed"    );     assert_eq!(        realpath_opts("b/.git".as_ref(), cwd, symlinks_disabled)?,        cwd.join("b").join(".git"),        "relative paths are prefixed with current dir"    );     assert_eq!(        realpath_opts("b//.git".as_ref(), cwd, symlinks_disabled)?,        cwd.join("b").join(".git"),        "empty path components are ignored"    );     assert_eq!(        realpath_opts("./tmp/.git".as_ref(), cwd, symlinks_disabled)?,        cwd.join("tmp").join(".git"),        "path starting with dot is relative and is prefixed with current dir"    );     assert_eq!(        realpath_opts("./tmp/a/./.git".as_ref(), cwd, symlinks_disabled)?,        cwd.join("tmp").join("a").join(".git"),        "all ./ path components are ignored unless they the one at the beginning of the path"    );     assert_eq!(        realpath_opts("./b/../tmp/.git".as_ref(), cwd, symlinks_disabled)?,        cwd.join("tmp").join(".git"),        "dot dot goes to parent path component"    );     {        #[cfg(not(windows))]        let absolute_path = Path::new("/c/d/.git");        #[cfg(windows)]        let absolute_path = Path::new(r"C:\c\d\.git");        assert_eq!(            realpath_opts(absolute_path, cwd, symlinks_disabled)?,            absolute_path,            "absolute path without symlinks has nothing to resolve and remains unchanged"        );    }     Ok(())} #[test]fn link_cycle_is_detected() -> crate::Result {    let tmp_dir = canonicalized_tempdir()?;    let dir = tmp_dir.path();    let link_name = "link";    let link_destination = dir.join(link_name);    let link_path = dir.join(link_name);    create_symlink(&link_path, link_destination)?;    let max_symlinks = 8;     assert!(        matches!(            realpath_opts(&link_path.join(".git"), "".as_ref(), max_symlinks),            Err(Error::MaxSymlinksExceeded { max_symlinks: 8 })        ),        "link cycle is detected"    );    Ok(())} #[test]fn symlink_with_absolute_path_gets_expanded() -> crate::Result {    let tmp_dir = canonicalized_tempdir()?;    let dir = tmp_dir.path();    let link_from = dir.join("a").join("b").join("tmp_p_q_link");    let link_to = dir.join("p").join("q");    create_symlink(&link_from, &link_to)?;    let max_symlinks = 8;    assert_eq!(        realpath_opts(&link_from.join(".git"), tmp_dir.path(), max_symlinks)?,        link_to.join(".git"),        "symlink with absolute path gets expanded"    );    Ok(())} #[test]fn symlink_to_relative_path_gets_expanded_into_absolute_path() -> crate::Result {    let cwd = canonicalized_tempdir()?;    let dir = cwd.path();    let link_name = "pq_link";    create_symlink(dir.join("r").join(link_name), Path::new("p").join("q"))?;    assert_eq!(        realpath_opts(&Path::new(link_name).join(".git"), &dir.join("r"), 8)?,        dir.join("r").join("p").join("q").join(".git"),        "symlink to relative path gets expanded into absolute path"    );    Ok(())} #[test]fn symlink_processing_is_disabled_if_the_value_is_zero() -> crate::Result {    let cwd = canonicalized_tempdir()?;    let link_name = "x_link";    create_symlink(cwd.path().join(link_name), Path::new("link destination does not exist"))?;    assert!(        matches!(            realpath_opts(&Path::new(link_name).join(".git"), cwd.path(), 0),            Err(Error::MaxSymlinksExceeded { max_symlinks: 0 })        ),        "symlink processing is disabled if the value is zero"    );    Ok(())} fn create_symlink(from: impl AsRef<Path>, to: impl AsRef<Path>) -> std::io::Result<()> {    std::fs::create_dir_all(from.as_ref().parent().unwrap())?;     #[cfg(not(windows))]    {        std::os::unix::fs::symlink(to, from)    }     #[cfg(windows)]    std::os::windows::fs::symlink_file(to, from)} fn canonicalized_tempdir() -> crate::Result<tempfile::TempDir> {    let canonicalized_tempdir = gix_path::realpath(std::env::temp_dir())?;    Ok(tempfile::tempdir_in(canonicalized_tempdir)?)}