use std::path::PathBuf; use testdir::testdir; use tokio::fs; use tokio::sync::OnceCell; use crate::fs_utils; use crate::git; use crate::grit; #[tokio::test] async fn test_fs_utils_create_dir_allow_existing() { let dir = testdir!(); let foo = dir.join("foo"); assert!(fs_utils::create_dir_allow_existing(&foo).await.is_ok()); assert!(fs::try_exists(&foo).await.unwrap()); assert!(fs_utils::create_dir_allow_existing(&foo).await.is_ok()); } #[tokio::test] async fn test_fs_utils_create_dir_allow_existing_file() { let dir = testdir!(); let foo = dir.join("foo"); assert!(fs::write(&foo, "hello").await.is_ok()); assert!(fs_utils::create_dir_allow_existing(&foo).await.is_err()); } #[tokio::test] async fn test_fs_utils_remove_file_allow_not_found() { let dir = testdir!(); let foo = dir.join("foo"); assert!(fs_utils::remove_file_allow_not_found(&foo).await.is_ok()); assert!(fs::write(&foo, "hello").await.is_ok()); assert!(fs_utils::remove_file_allow_not_found(&foo).await.is_ok()); assert!(!fs::try_exists(&foo).await.unwrap()); } #[tokio::test] async fn test_fs_utils_symlink_update_existing() { let dir = testdir!(); let foo = dir.join("foo"); let bar = dir.join("bar"); let fum = dir.join("fum"); assert!(fs::write(&foo, "hello").await.is_ok()); assert!(fs_utils::symlink_update_existing(&foo, &bar).await.is_ok()); assert!(fs_utils::symlink_update_existing(&foo, &bar).await.is_ok()); assert_eq!(fs::read_link(&bar).await.unwrap(), foo); assert!(fs_utils::symlink_update_existing(&fum, &bar).await.is_ok()); assert_eq!(fs::read_link(&bar).await.unwrap(), fum); } static BARE: OnceCell = OnceCell::const_new(); async fn git_setup(bare: bool) -> git::Repository { let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")) .join("src/testdata") .join(if bare { "bare" } else { "work" }); let repo = git::Repository::new( path.clone(), bare, None::, None::, None::, None::, ); assert_eq!(repo.remote(), None); assert_eq!(repo.project_id(), None); assert_eq!(repo.path(), path); assert_eq!(repo.socket(), None); assert_eq!(repo.is_bare(), bare); repo.setup().await.unwrap(); repo } async fn git_config_get(repo: &git::Repository) { assert_eq!(repo.config_get("user.name").await.unwrap(), "John Smith"); assert_eq!( repo.config_get("user.email").await.unwrap(), "jsmith@example.org" ); assert_eq!(repo.config_get("eyeballs.foo").await.unwrap(), "bar"); assert_eq!(repo.config_get("eyeballs.bar").await.unwrap(), ""); } async fn git_is_ancestor(repo: &git::Repository) { assert_eq!( repo.is_ancestor( "807fffaad7b35683162669a485ce3e995d56170d", "d7c502b9c6b833060576a0c4da0287933d603011", ) .await .unwrap(), true, ); assert_eq!( repo.is_ancestor( "d7c502b9c6b833060576a0c4da0287933d603011", "807fffaad7b35683162669a485ce3e995d56170d", ) .await .unwrap(), false, ); assert_eq!( repo.is_ancestor( "807fffaad7b35683162669a485ce3e995d56170d", "807fffaad7b35683162669a485ce3e995d56170d", ) .await .unwrap(), true, ); assert_eq!( repo.is_ancestor( "2d05d489d42d4f36dd0ebf52502f243991e010eb", "2cecdec660a30bf3964cee645d9cee03640ef8dc", ) .await .unwrap(), false, ); assert!(repo .is_ancestor( "1234567890123456789012345678901234567890", "2cecdec660a30bf3964cee645d9cee03640ef8dc", ) .await .is_err(),); assert!(repo.is_ancestor("", "'\"",).await.is_err(),); } async fn git_is_equal_content(repo: &git::Repository) { assert_eq!( repo.is_equal_content( "d7c502b9c6b833060576a0c4da0287933d603011", "d7c502b9c6b833060576a0c4da0287933d603011", ) .await .unwrap(), true, ); assert_eq!( repo.is_equal_content( "d7c502b9c6b833060576a0c4da0287933d603011", "2d05d489d42d4f36dd0ebf52502f243991e010eb", ) .await .unwrap(), true, ); assert_eq!( repo.is_equal_content( "d7c502b9c6b833060576a0c4da0287933d603011", "2cecdec660a30bf3964cee645d9cee03640ef8dc", ) .await .unwrap(), false, ); assert!(repo .is_equal_content( "1234567890123456789012345678901234567890", "2cecdec660a30bf3964cee645d9cee03640ef8dc", ) .await .is_err(),); assert!(repo.is_equal_content("", "'\"",).await.is_err(),); } async fn git_get_author_commiter(repo: &git::Repository) { let a1 = repo .get_author("d7c502b9c6b833060576a0c4da0287933d603011") .await .unwrap(); assert_eq!(a1.name, "John Smith"); assert_eq!(a1.email, "jsmith@example.org"); assert_eq!(a1.username, "jsmith"); let c1 = repo .get_commiter("d7c502b9c6b833060576a0c4da0287933d603011") .await .unwrap(); assert_eq!(c1.name, a1.name); assert_eq!(c1.email, a1.email); assert_eq!(c1.username, a1.username); let a2 = repo .get_author("2cecdec660a30bf3964cee645d9cee03640ef8dc") .await .unwrap(); assert_eq!(a2.name, "Test"); assert_eq!(a2.email, "testing@example.org"); assert_eq!(a2.username, "testing"); let c2 = repo .get_commiter("d7c502b9c6b833060576a0c4da0287933d603011") .await .unwrap(); assert_eq!(c2.name, c1.name); assert_eq!(c2.email, c1.email); assert_eq!(c2.username, c1.username); assert!(repo .get_author("1234567890123456789012345678901234567890") .await .is_err()); assert!(repo.get_author("").await.is_err()); } async fn git_fetch(bare: bool) -> git::Repository { let path = testdir!().join("repo"); let remote_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("src/testdata/bare"); let remote = remote_path.to_string_lossy().into_owned(); let repo = git::Repository::new( path, bare, Some(remote.as_str()), None::, None::, None::, ); assert_eq!(repo.remote(), Some(remote.as_str())); repo.setup().await.unwrap(); if bare { let (main, branch, other) = tokio::join!( repo.fetch("main"), repo.fetch("branch"), repo.fetch("other"), ); main.unwrap(); branch.unwrap(); other.unwrap(); } else { // Not bare repo will complain when you try to fetch into the currently checked // out branch. So just try fetching other branches. let (branch, other) = tokio::join!(repo.fetch("branch"), repo.fetch("other")); branch.unwrap(); other.unwrap(); } repo } #[tokio::test] async fn test_git_bare_config_get() { let repo = BARE.get_or_init(|| git_setup(true)).await; git_config_get(repo).await; } #[tokio::test] async fn test_git_bare_is_ancestor() { let repo = BARE.get_or_init(|| git_setup(true)).await; git_is_ancestor(repo).await; } #[tokio::test] async fn test_git_bare_is_equal_content() { let repo = BARE.get_or_init(|| git_setup(true)).await; git_is_equal_content(repo).await; } #[tokio::test] async fn test_git_bare_get_author_commiter() { let repo = BARE.get_or_init(|| git_setup(true)).await; git_get_author_commiter(repo).await; } #[tokio::test] async fn test_git_fetch() { git_fetch(false).await; } #[tokio::test] async fn test_git_bare_fetch() { git_fetch(true).await; } #[tokio::test] async fn test_git_delete_branch() { // Using git_fetch as we need a writeable git repo let repo = git_fetch(false).await; assert!(repo.delete_branch("other").await.is_ok()); assert!(repo.delete_branch("does-not-exist").await.is_err()); } #[tokio::test] async fn test_git_bare_delete_branch() { // Using git_fetch as we need a writeable git repo let repo = git_fetch(true).await; assert!(repo.delete_branch("other").await.is_ok()); assert!(repo.delete_branch("does-not-exist").await.is_err()); } #[tokio::test] async fn test_grit_parse_base() { let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("src/testdata/grit/base.grd"); let grit = grit::parse_grit(path).await.unwrap(); assert_eq!( grit, grit::Grit { current_release: 1, latest_public_release: 0, outputs: grit::Outputs { output: vec![ grit::IfOutput::Output( grit::Output { filename: "values/strings.xml".to_string(), output_type: "android".to_string(), lang: "en".to_string(), }, ), grit::IfOutput::Output( grit::Output { filename: "values-en-rGB/strings.xml".to_string(), output_type: "android".to_string(), lang: "en-GB".to_string(), }, ), grit::IfOutput::Output( grit::Output { filename: "values-my/strings.xml".to_string(), output_type: "android".to_string(), lang: "my".to_string(), }, ), grit::IfOutput::If { expr: "not pp_if('zawgyi_encoding')".to_string(), output: vec![ grit::IfOutput::Output( grit::Output { filename: "values-my-rZG/strings.xml".to_string(), output_type: "android".to_string(), lang: "my-ZG".to_string(), }, ), ], }, grit::IfOutput::Output( grit::Output { filename: "values-sv/strings.xml".to_string(), output_type: "android".to_string(), lang: "sv".to_string(), }, ), ], }, translations: grit::Translations { file: vec![ grit::IfFile::File( grit::File { path: "translations/base_en_gb.xlf".to_string(), lang: "en-GB".to_string(), }, ), grit::IfFile::If { expr: "pp_if('zawgyi_encoding')".to_string(), file: vec![ grit::IfFile::File( grit::File { path: "translations/base_my-Zawgyi.xlf".to_string(), lang: "my".to_string(), }, ), ], }, grit::IfFile::If { expr: "not pp_if('zawgyi_encoding')".to_string(), file: vec![ grit::IfFile::File( grit::File { path: "translations/base_my.xlf".to_string(), lang: "my".to_string(), }, ), grit::IfFile::File( grit::File { path: "translations/base_my-Zawgyi.xlf".to_string(), lang: "my-ZG".to_string(), }, ), ], }, grit::IfFile::File( grit::File { path: "translations/base_sv.xlf".to_string(), lang: "sv".to_string(), }, ), ], }, release: grit::Release { allow_pseudo: false, seq: 1, messages: grit::Messages { fallback_to_english: true, messages: vec![ grit::IfMessagePart::If { expr: "pp_ifdef('include_extra')".to_string(), message: vec![ grit::IfMessagePart::Part( grit::PartRef { file: "extra.grdp".to_string(), }, ), ], }, grit::IfMessagePart::Message( grit::Message { desc: "Title which is shown on the main bookmarks view.".to_string(), name: "IDS_BOOKMARKS_FRAGMENT_TITLE".to_string(), internal_comment: Some("section(bookmarks)".to_string()), meaning: None, content: vec![ grit::TextPlaceholder::Text("Bookmarks".to_string()), ], }, ), grit::IfMessagePart::Message( grit::Message { desc: "Generic welcome string.".to_string(), name: "IDS_GENERIC_WELCOME".to_string(), internal_comment: Some("section(eula)".to_string()), meaning: None, content: vec![ grit::TextPlaceholder::Text("Welcome to ".to_string()), grit::TextPlaceholder::Placeholder { name: "STRING".to_string(), content: "%1$s".to_string(), example: Some("Opera".to_string()), }, ], }, ), grit::IfMessagePart::Message( grit::Message { desc: "First startup information about the license and privacy terms.".to_string(), name: "IDS_START_TERMS".to_string(), internal_comment: None, meaning: None, content: vec![ grit::TextPlaceholder::Text( "By using this application you are agreeing to Opera's ".to_string(), ), grit::TextPlaceholder::Placeholder { name: "TOS_BEGIN".to_string(), content: "".to_string(), example: None, }, grit::TextPlaceholder::Text( "Terms of Service".to_string(), ), grit::TextPlaceholder::Placeholder { name: "TOS_END".to_string(), content: "".to_string(), example: None, }, grit::TextPlaceholder::Text( ". Also, you can learn how Opera handles and protects your data in our ".to_string(), ), grit::TextPlaceholder::Placeholder { name: "PRIVACY_BEGIN".to_string(), content: "".to_string(), example: None, }, grit::TextPlaceholder::Text( "Privacy Statement".to_string(), ), grit::TextPlaceholder::Placeholder { name: "PRIVACY_END".to_string(), content: "".to_string(), example: None, }, grit::TextPlaceholder::Text( ".".to_string(), ), ], }, ), grit::IfMessagePart::Message( grit::Message { desc: "Message which is shown when one or more folders have been deleted from the bookmark list.".to_string(), name: "IDS_BOOKMARKS_FOLDERS_DELETED".to_string(), internal_comment: None, meaning: None, content: vec![ grit::TextPlaceholder::Text( "{BOOKMARKS, plural,\n one {".to_string(), ), grit::TextPlaceholder::Placeholder { name: "COUNT".to_string(), content: "%1$d".to_string(), example: Some("1".to_string()), }, grit::TextPlaceholder::Text( " folder deleted}\n few {".to_string(), ), grit::TextPlaceholder::Placeholder { name: "COUNT".to_string(), content: "%1$d".to_string(), example: Some("15".to_string()), }, grit::TextPlaceholder::Text( " folders deleted}\n many {".to_string(), ), grit::TextPlaceholder::Placeholder { name: "COUNT".to_string(), content: "%1$d".to_string(), example: Some("100".to_string()), }, grit::TextPlaceholder::Text( " folders deleted}\n other {".to_string(), ), grit::TextPlaceholder::Placeholder { name: "COUNT".to_string(), content: "%1$d".to_string(), example: Some("42".to_string()), }, grit::TextPlaceholder::Text( " folders deleted}}".to_string(), ), ], }, ), ], }, }, }, ) }