Svetlin StefanovRefactor git_config tests.714ef5c4 years agoHistory
1163 lines · 33.4 KB · Rust
RawDownload
#[cfg(test)]mod mutable_value {    use git_config::file::GitConfig;    use std::convert::TryFrom;     fn init_config() -> GitConfig<'static> {        GitConfig::try_from(            r#"[core]                a=b"100"            [core]                c=d                e=f"#,        )        .unwrap()    }     #[test]    fn value_is_correct() {        let mut git_config = init_config();         let value = git_config.get_raw_value_mut("core", None, "a").unwrap();        assert_eq!(&*value.get().unwrap(), b"b100");    }     #[test]    fn set_string_cleanly_updates() {        let mut git_config = init_config();         let mut value = git_config.get_raw_value_mut("core", None, "a").unwrap();        value.set_string("hello world".to_string());        assert_eq!(            git_config.to_string(),            r#"[core]                a=hello world            [core]                c=d                e=f"#,        );         let mut value = git_config.get_raw_value_mut("core", None, "e").unwrap();        value.set_string(String::new());        assert_eq!(            git_config.to_string(),            r#"[core]                a=hello world            [core]                c=d                e="#,        );    }     #[test]    fn delete_value() {        let mut git_config = init_config();         let mut value = git_config.get_raw_value_mut("core", None, "a").unwrap();        value.delete();        assert_eq!(            git_config.to_string(),            "[core]\n                \n            [core]                c=d                e=f",        );         let mut value = git_config.get_raw_value_mut("core", None, "c").unwrap();        value.delete();        assert_eq!(            git_config.to_string(),            "[core]\n                \n            [core]\n                \n                e=f",        );    }     #[test]    fn get_value_after_deleted() {        let mut git_config = init_config();         let mut value = git_config.get_raw_value_mut("core", None, "a").unwrap();        value.delete();        assert!(value.get().is_err());    }     #[test]    fn set_string_after_deleted() {        let mut git_config = init_config();         let mut value = git_config.get_raw_value_mut("core", None, "a").unwrap();        value.delete();        value.set_string("hello world".to_string());        assert_eq!(            git_config.to_string(),            r#"[core]                a=hello world            [core]                c=d                e=f"#,        );    }     #[test]    fn subsequent_delete_calls_are_noop() {        let mut git_config = init_config();         let mut value = git_config.get_raw_value_mut("core", None, "a").unwrap();        for _ in 0..10 {            value.delete();        }        assert_eq!(            git_config.to_string(),            "[core]\n                \n            [core]                c=d                e=f",        );    }     #[test]    fn partial_values_are_supported() {        let mut git_config = GitConfig::try_from(            r#"[core]                a=b"100"\b            [core]                c=d                e=f"#,        )        .unwrap();        let mut value = git_config.get_raw_value_mut("core", None, "a").unwrap();        assert_eq!(&*value.get().unwrap(), b"b100b");        value.delete();        assert_eq!(            git_config.to_string(),            "[core]\n                \n            [core]                c=d                e=f",        );    }} #[cfg(test)]mod mutable_multi_value {    use git_config::file::GitConfig;    use std::{borrow::Cow, convert::TryFrom};     fn init_config() -> GitConfig<'static> {        GitConfig::try_from(            r#"[core]                a=b"100"            [core]                a=d                a=f"#,        )        .unwrap()    }     #[test]    fn value_is_correct() {        let mut git_config = init_config();         let value = git_config.get_raw_multi_value_mut("core", None, "a").unwrap();        assert_eq!(            &*value.get().unwrap(),            vec![                Cow::<[u8]>::Owned(b"b100".to_vec()),                Cow::<[u8]>::Borrowed(b"d"),                Cow::<[u8]>::Borrowed(b"f"),            ]        );    }     #[test]    fn non_empty_sizes_are_correct() {        let mut git_config = init_config();        assert_eq!(git_config.get_raw_multi_value_mut("core", None, "a").unwrap().len(), 3);        assert!(!git_config            .get_raw_multi_value_mut("core", None, "a")            .unwrap()            .is_empty());    }     #[test]    fn set_value_at_start() {        let mut git_config = init_config();        let mut values = git_config.get_raw_multi_value_mut("core", None, "a").unwrap();        values.set_string(0, "Hello".to_string());        assert_eq!(            git_config.to_string(),            r#"[core]                a=Hello            [core]                a=d                a=f"#,        );    }     #[test]    fn set_value_at_end() {        let mut git_config = init_config();        let mut values = git_config.get_raw_multi_value_mut("core", None, "a").unwrap();        values.set_string(2, "Hello".to_string());        assert_eq!(            git_config.to_string(),            r#"[core]                a=b"100"            [core]                a=d                a=Hello"#,        );    }     #[test]    fn set_values_all() {        let mut git_config = init_config();        let mut values = git_config.get_raw_multi_value_mut("core", None, "a").unwrap();        values.set_owned_values_all(b"Hello");        assert_eq!(            git_config.to_string(),            r#"[core]                a=Hello            [core]                a=Hello                a=Hello"#,        );    }     #[test]    fn delete() {        let mut git_config = init_config();        let mut values = git_config.get_raw_multi_value_mut("core", None, "a").unwrap();        values.delete(0);        assert_eq!(            git_config.to_string(),            "[core]\n                \n            [core]                a=d                a=f",        );    }     #[test]    fn delete_all() {        let mut git_config = init_config();        let mut values = git_config.get_raw_multi_value_mut("core", None, "a").unwrap();        values.delete_all();        assert!(values.get().is_err());        assert_eq!(            git_config.to_string(),            "[core]\n                \n            [core]\n                \n                ",        );    }     #[test]    fn partial_values_are_supported() {        let mut git_config = GitConfig::try_from(            r#"[core]                a=b\"100"            [core]                a=d\b                a=f\a"#,        )        .unwrap();        let mut values = git_config.get_raw_multi_value_mut("core", None, "a").unwrap();         assert_eq!(            &*values.get().unwrap(),            vec![                Cow::<[u8]>::Owned(b"b100".to_vec()),                Cow::<[u8]>::Borrowed(b"db"),                Cow::<[u8]>::Borrowed(b"fa"),            ]        );         values.delete_all();        assert!(values.get().is_err());    }} #[cfg(test)]mod from_paths_tests {    use std::borrow::Cow;    use std::path::Path;    use std::{fs, io};     use git_config::file::from_paths::Error;    use git_config::file::{from_paths, GitConfig};    use git_config::parser::ParserOrIoError;    use tempfile::tempdir;     /// Escapes backslash when writing a path as string so that it is a valid windows path    fn escape_backslashes(path: &std::path::Path) -> String {        path.to_str().unwrap().replace('\\', "\\\\")    }     #[test]    fn parse_config_with_windows_line_endings_successfully() -> crate::Result {        GitConfig::open(Path::new("tests").join("fixtures").join("repo-config.crlf"))?;        Ok(())    }     #[test]    fn file_not_found() {        let dir = tempdir().unwrap();        let config_path = dir.path().join("config");         let paths = vec![config_path];        let error = GitConfig::from_paths(paths, &Default::default()).unwrap_err();        assert!(            matches!(error,  Error::ParserOrIoError(ParserOrIoError::Io(io_error)) if io_error.kind() == io::ErrorKind::NotFound)        );    }     #[test]    fn single_path() {        let dir = tempdir().unwrap();        let config_path = dir.path().join("config");        fs::write(config_path.as_path(), b"[core]\nboolean = true").unwrap();         let paths = vec![config_path];        let config = GitConfig::from_paths(paths, &Default::default()).unwrap();         assert_eq!(            config.get_raw_value("core", None, "boolean"),            Ok(Cow::<[u8]>::Borrowed(b"true"))        );         assert_eq!(config.len(), 1);    }     #[test]    fn multiple_includes() {        let dir = tempdir().unwrap();         let a_path = dir.path().join("a");        fs::write(            a_path.as_path(),            "            [core]              a = false              sslVerify = true              d = 41",        )        .unwrap();         let b_path = dir.path().join("b");        let relative_b_path: std::path::PathBuf = "b".into();        fs::write(            b_path.as_path(),            "            [diff]              renames = true",        )        .unwrap();        let ignore_path = dir.path().join("ignore");        fs::write(            ignore_path.as_path(),            "            [diff]              renames = invalid",        )        .unwrap();         let a_path_string = escape_backslashes(a_path.parent().unwrap());        let non_canonical_path_a = format!("{}/./a", a_path_string);        let non_existing_path = "/dfgwfsghfdsfs";        let c_path = dir.path().join("c");        fs::write(            c_path.as_path(),            format!(                "            [core]              c = 12              d = 42            [include]              path = {}              path = {}              path = {}            [include.ignore]              path = {}            [http]	          sslVerify = false",                non_existing_path,                non_canonical_path_a,                relative_b_path.as_path().to_str().unwrap(),                escape_backslashes(&ignore_path)            ),        )        .unwrap();         let config = GitConfig::from_paths(vec![c_path], &Default::default()).unwrap();         assert_eq!(            config.get_raw_value("core", None, "c"),            Ok(Cow::<[u8]>::Borrowed(b"12"))        );        assert_eq!(            config.get_raw_value("core", None, "d"),            Ok(Cow::<[u8]>::Borrowed(b"41"))        );        assert_eq!(            config.get_raw_value("http", None, "sslVerify"),            Ok(Cow::<[u8]>::Borrowed(b"false"))        );         assert_eq!(            config.get_raw_value("diff", None, "renames"),            Ok(Cow::<[u8]>::Borrowed(b"true"))        );         assert_eq!(            config.get_raw_value("core", None, "a"),            Ok(Cow::<[u8]>::Borrowed(b"false"))        );    }     #[test]    fn nested_include_respects_max_depth() {        let dir = tempdir().unwrap();         // 0 includes 1 - base level        // 1 includes 2        // 2 includes 3        // 3 includes 4        // 4 has no includes        let max_depth = 4u8;        for (i, next_i) in (0..max_depth).zip(1..=max_depth) {            let path = dir.path().join(i.to_string());            let next_path = dir.path().join(next_i.to_string());            fs::write(                path.as_path(),                format!(                    "                    [core]                      i = {i}                     [include]                      path = {}",                    escape_backslashes(&next_path),                ),            )            .unwrap();        }         fs::write(            dir.path().join(max_depth.to_string()),            "                    [core]                      i = {}"                .replace("{}", &max_depth.to_string()),        )        .unwrap();         let options = from_paths::Options::default();        let config = GitConfig::from_paths(vec![dir.path().join("0")], &options).unwrap();        assert_eq!(            config.get_raw_multi_value("core", None, "i").unwrap(),            vec![                Cow::Borrowed(b"0"),                Cow::Borrowed(b"1"),                Cow::Borrowed(b"2"),                Cow::Borrowed(b"3"),                Cow::Borrowed(b"4")            ]        );         // with max_allowed_depth of 1 and 4 levels of includes and error_on_max_depth_exceeded: false, max_allowed_depth is exceeded and the value of level 1 is returned        // this is equivalent to running git with --no-includes option        let options = from_paths::Options {            max_depth: 1,            error_on_max_depth_exceeded: false,            ..Default::default()        };        let config = GitConfig::from_paths(vec![dir.path().join("0")], &options).unwrap();        assert_eq!(config.get_raw_value("core", None, "i"), Ok(Cow::<[u8]>::Borrowed(b"1")));         // with default max_allowed_depth of 10 and 4 levels of includes, last level is read        let options = from_paths::Options::default();        let config = GitConfig::from_paths(vec![dir.path().join("0")], &options).unwrap();        assert_eq!(config.get_raw_value("core", None, "i"), Ok(Cow::<[u8]>::Borrowed(b"4")));         // with max_allowed_depth of 5, the base and 4 levels of includes, last level is read        let options = from_paths::Options {            max_depth: 5,            ..Default::default()        };        let config = GitConfig::from_paths(vec![dir.path().join("0")], &options).unwrap();        assert_eq!(config.get_raw_value("core", None, "i"), Ok(Cow::<[u8]>::Borrowed(b"4")));         // with max_allowed_depth of 2 and 4 levels of includes, max_allowed_depth is exceeded and error is returned        let options = from_paths::Options {            max_depth: 2,            ..Default::default()        };        let config = GitConfig::from_paths(vec![dir.path().join("0")], &options);        assert!(matches!(            config.unwrap_err(),            from_paths::Error::IncludeDepthExceeded { max_depth: 2 }        ));         // with max_allowed_depth of 2 and 4 levels of includes and error_on_max_depth_exceeded: false , max_allowed_depth is exceeded and the value of level 2 is returned        let options = from_paths::Options {            max_depth: 2,

Lines 1–500 of 1163.