From 409edadef280e578fb202b96fb5b5dfa979cc620 Mon Sep 17 00:00:00 2001 From: Daniel Szoke Date: Wed, 10 Sep 2025 13:54:13 +0200 Subject: [PATCH] ref(clippy): Enable `tests-outside-test-module` lint Enable the [`tests-outside-test-module`](https://rust-lang.github.io/rust-clippy/master/index.html#tests_outside_test_module) Clippy lint, and fix violations. This lint will enforce the convention that `#[test]` items must be placed within a `#[cfg(test)]` module. --- Cargo.toml | 1 + src/commands/mod.rs | 11 +- src/commands/sourcemaps/explain.rs | 95 +- src/utils/http.rs | 75 +- ...cli__utils__vcs__get_commits_from_git.snap | 20 - ...tests__generate_patch_default_twenty.snap} | 0 ...tests__generate_patch_ignore_missing.snap} | 0 ..._vcs__tests__generate_patch_set_base.snap} | 0 ...__generate_patch_set_previous_commit.snap} | 0 ...ils__vcs__tests__get_commits_from_git.snap | 20 + src/utils/vcs.rs | 1143 ++++++++--------- src/utils/xcode.rs | 39 +- 12 files changed, 711 insertions(+), 693 deletions(-) delete mode 100644 src/utils/snapshots/sentry_cli__utils__vcs__get_commits_from_git.snap rename src/utils/snapshots/{sentry_cli__utils__vcs__generate_patch_default_twenty.snap => sentry_cli__utils__vcs__tests__generate_patch_default_twenty.snap} (100%) rename src/utils/snapshots/{sentry_cli__utils__vcs__generate_patch_ignore_missing.snap => sentry_cli__utils__vcs__tests__generate_patch_ignore_missing.snap} (100%) rename src/utils/snapshots/{sentry_cli__utils__vcs__generate_patch_set_base.snap => sentry_cli__utils__vcs__tests__generate_patch_set_base.snap} (100%) rename src/utils/snapshots/{sentry_cli__utils__vcs__generate_patch_set_previous_commit.snap => sentry_cli__utils__vcs__tests__generate_patch_set_previous_commit.snap} (100%) create mode 100644 src/utils/snapshots/sentry_cli__utils__vcs__tests__get_commits_from_git.snap diff --git a/Cargo.toml b/Cargo.toml index f0a0931c91..e78eb975f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -98,6 +98,7 @@ with_crash_reporting = [] allow-attributes = "warn" str-to-string = "warn" string-to-string = "warn" +tests-outside-test-module = "warn" unnecessary-wraps = "warn" uninlined-format-args = "warn" unused-trait-names = "warn" diff --git a/src/commands/mod.rs b/src/commands/mod.rs index a149e66394..f20f5958df 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -392,7 +392,12 @@ pub fn main() -> ! { process::exit(exit_code); } -#[test] -fn verify_app() { - app().debug_assert(); +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn verify_app() { + app().debug_assert(); + } } diff --git a/src/commands/sourcemaps/explain.rs b/src/commands/sourcemaps/explain.rs index f57d8ee878..f0c7bcef02 100644 --- a/src/commands/sourcemaps/explain.rs +++ b/src/commands/sourcemaps/explain.rs @@ -467,52 +467,57 @@ pub fn execute(matches: &ArgMatches) -> Result<()> { Ok(()) } -#[test] -fn test_resolve_sourcemap_url() { - // Tests coming from `tests/sentry/utils/test_urls.py` in `getsentry/sentry` - let cases = vec![ - ("http://example.com/foo", "bar", "http://example.com/bar"), - ("http://example.com/foo", "/bar", "http://example.com/bar"), - ("https://example.com/foo", "/bar", "https://example.com/bar"), - ( - "http://example.com/foo/baz", - "bar", - "http://example.com/foo/bar", - ), - ( - "http://example.com/foo/baz", - "/bar", - "http://example.com/bar", - ), - ("aps://example.com/foo", "/bar", "aps://example.com/bar"), - ( - "apsunknown://example.com/foo", - "/bar", - "apsunknown://example.com/bar", - ), - ( - "apsunknown://example.com/foo", - "//aha/uhu", - "apsunknown://aha/uhu", - ), - ]; - - for (base, to_join, expected) in cases { - assert_eq!(resolve_sourcemap_url(base, to_join).unwrap(), expected); +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_resolve_sourcemap_url() { + // Tests coming from `tests/sentry/utils/test_urls.py` in `getsentry/sentry` + let cases = vec![ + ("http://example.com/foo", "bar", "http://example.com/bar"), + ("http://example.com/foo", "/bar", "http://example.com/bar"), + ("https://example.com/foo", "/bar", "https://example.com/bar"), + ( + "http://example.com/foo/baz", + "bar", + "http://example.com/foo/bar", + ), + ( + "http://example.com/foo/baz", + "/bar", + "http://example.com/bar", + ), + ("aps://example.com/foo", "/bar", "aps://example.com/bar"), + ( + "apsunknown://example.com/foo", + "/bar", + "apsunknown://example.com/bar", + ), + ( + "apsunknown://example.com/foo", + "//aha/uhu", + "apsunknown://aha/uhu", + ), + ]; + + for (base, to_join, expected) in cases { + assert_eq!(resolve_sourcemap_url(base, to_join).unwrap(), expected); + } } -} -#[test] -fn test_unify_artifact_url() { - let cases = vec![ - ( - "http://localhost:5000/dist/bundle.min.js", - "~/dist/bundle.min.js", - ), - ("/dist/bundle.js.map", "~/dist/bundle.js.map"), - ]; - - for (path, expected) in cases { - assert_eq!(unify_artifact_url(path).unwrap(), expected); + #[test] + fn test_unify_artifact_url() { + let cases = vec![ + ( + "http://localhost:5000/dist/bundle.min.js", + "~/dist/bundle.min.js", + ), + ("/dist/bundle.js.map", "~/dist/bundle.js.map"), + ]; + + for (path, expected) in cases { + assert_eq!(unify_artifact_url(path).unwrap(), expected); + } } } diff --git a/src/utils/http.rs b/src/utils/http.rs index 37a531ff5c..6ea043369e 100644 --- a/src/utils/http.rs +++ b/src/utils/http.rs @@ -72,40 +72,45 @@ pub fn is_absolute_url(url: &str) -> bool { url.starts_with("http://") || url.starts_with("https://") } -#[test] -fn test_parse_link_header() { - let rv = parse_link_header("; rel=\"previous\"; results=\"false\"; cursor=\"100:-1:1\", ; rel=\"next\"; results=\"true\"; cursor=\"100:1:0\""); - assert_eq!(rv.len(), 2); - - let a = &rv[0]; - let b = &rv[1]; - - assert_eq!( - a.get("_link").unwrap(), - &"https://sentry.io/api/0/organizations/sentry/releases/?&cursor=100:-1:1" - ); - assert_eq!(a.get("cursor").unwrap(), &"100:-1:1"); - assert_eq!(a.get("rel").unwrap(), &"previous"); - assert_eq!(a.get("results").unwrap(), &"false"); - - assert_eq!( - b.get("_link").unwrap(), - &"https://sentry.io/api/0/organizations/sentry/releases/?&cursor=100:1:0" - ); - assert_eq!(b.get("cursor").unwrap(), &"100:1:0"); - assert_eq!(b.get("rel").unwrap(), &"next"); - assert_eq!(b.get("results").unwrap(), &"true"); -} +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_parse_link_header() { + let rv = parse_link_header("; rel=\"previous\"; results=\"false\"; cursor=\"100:-1:1\", ; rel=\"next\"; results=\"true\"; cursor=\"100:1:0\""); + assert_eq!(rv.len(), 2); + + let a = &rv[0]; + let b = &rv[1]; + + assert_eq!( + a.get("_link").unwrap(), + &"https://sentry.io/api/0/organizations/sentry/releases/?&cursor=100:-1:1" + ); + assert_eq!(a.get("cursor").unwrap(), &"100:-1:1"); + assert_eq!(a.get("rel").unwrap(), &"previous"); + assert_eq!(a.get("results").unwrap(), &"false"); -#[test] -fn test_is_absolute_url() { - assert!(is_absolute_url("https://sentry.io")); - assert!(is_absolute_url("http://sentry.io")); - assert!(is_absolute_url("https://sentry.io/path")); - assert!(is_absolute_url("http://sentry.io/path")); - assert!(is_absolute_url("http://sentry.io/path?query=foo")); - assert!(is_absolute_url("https://sentry.io/path?query=foo")); - - assert!(!is_absolute_url("/path")); - assert!(!is_absolute_url("/path?query=foo")); + assert_eq!( + b.get("_link").unwrap(), + &"https://sentry.io/api/0/organizations/sentry/releases/?&cursor=100:1:0" + ); + assert_eq!(b.get("cursor").unwrap(), &"100:1:0"); + assert_eq!(b.get("rel").unwrap(), &"next"); + assert_eq!(b.get("results").unwrap(), &"true"); + } + + #[test] + fn test_is_absolute_url() { + assert!(is_absolute_url("https://sentry.io")); + assert!(is_absolute_url("http://sentry.io")); + assert!(is_absolute_url("https://sentry.io/path")); + assert!(is_absolute_url("http://sentry.io/path")); + assert!(is_absolute_url("http://sentry.io/path?query=foo")); + assert!(is_absolute_url("https://sentry.io/path?query=foo")); + + assert!(!is_absolute_url("/path")); + assert!(!is_absolute_url("/path?query=foo")); + } } diff --git a/src/utils/snapshots/sentry_cli__utils__vcs__get_commits_from_git.snap b/src/utils/snapshots/sentry_cli__utils__vcs__get_commits_from_git.snap deleted file mode 100644 index a3828d4175..0000000000 --- a/src/utils/snapshots/sentry_cli__utils__vcs__get_commits_from_git.snap +++ /dev/null @@ -1,20 +0,0 @@ ---- -source: src/utils/vcs.rs -expression: "commits.0.iter().map(|c|\n {\n (c.author().name().unwrap().to_owned(),\n c.author().email().unwrap().to_owned(),\n c.summary())\n }).collect::>()" ---- -[ - ( - "John Doe", - "john.doe@example.com", - Some( - "\"second commit\"", - ), - ), - ( - "John Doe", - "john.doe@example.com", - Some( - "\"initial commit\"", - ), - ), -] diff --git a/src/utils/snapshots/sentry_cli__utils__vcs__generate_patch_default_twenty.snap b/src/utils/snapshots/sentry_cli__utils__vcs__tests__generate_patch_default_twenty.snap similarity index 100% rename from src/utils/snapshots/sentry_cli__utils__vcs__generate_patch_default_twenty.snap rename to src/utils/snapshots/sentry_cli__utils__vcs__tests__generate_patch_default_twenty.snap diff --git a/src/utils/snapshots/sentry_cli__utils__vcs__generate_patch_ignore_missing.snap b/src/utils/snapshots/sentry_cli__utils__vcs__tests__generate_patch_ignore_missing.snap similarity index 100% rename from src/utils/snapshots/sentry_cli__utils__vcs__generate_patch_ignore_missing.snap rename to src/utils/snapshots/sentry_cli__utils__vcs__tests__generate_patch_ignore_missing.snap diff --git a/src/utils/snapshots/sentry_cli__utils__vcs__generate_patch_set_base.snap b/src/utils/snapshots/sentry_cli__utils__vcs__tests__generate_patch_set_base.snap similarity index 100% rename from src/utils/snapshots/sentry_cli__utils__vcs__generate_patch_set_base.snap rename to src/utils/snapshots/sentry_cli__utils__vcs__tests__generate_patch_set_base.snap diff --git a/src/utils/snapshots/sentry_cli__utils__vcs__generate_patch_set_previous_commit.snap b/src/utils/snapshots/sentry_cli__utils__vcs__tests__generate_patch_set_previous_commit.snap similarity index 100% rename from src/utils/snapshots/sentry_cli__utils__vcs__generate_patch_set_previous_commit.snap rename to src/utils/snapshots/sentry_cli__utils__vcs__tests__generate_patch_set_previous_commit.snap diff --git a/src/utils/snapshots/sentry_cli__utils__vcs__tests__get_commits_from_git.snap b/src/utils/snapshots/sentry_cli__utils__vcs__tests__get_commits_from_git.snap new file mode 100644 index 0000000000..ca38f79a3e --- /dev/null +++ b/src/utils/snapshots/sentry_cli__utils__vcs__tests__get_commits_from_git.snap @@ -0,0 +1,20 @@ +--- +source: src/utils/vcs.rs +expression: "commits.0.iter().map(|c|\n{\n (c.author().name().unwrap().to_owned(),\n c.author().email().unwrap().to_owned(), c.summary(),)\n}).collect::>()" +--- +[ + ( + "John Doe", + "john.doe@example.com", + Some( + "\"second commit\"", + ), + ), + ( + "John Doe", + "john.doe@example.com", + Some( + "\"initial commit\"", + ), + ), +] diff --git a/src/utils/vcs.rs b/src/utils/vcs.rs index 9fb1d1da89..c883b90400 100644 --- a/src/utils/vcs.rs +++ b/src/utils/vcs.rs @@ -668,642 +668,639 @@ pub fn get_commit_time(time: Time) -> DateTime { } #[cfg(test)] -use { - crate::api::RepoProvider, - insta::{assert_debug_snapshot, assert_yaml_snapshot}, - std::fs::File, - std::io::Write as _, - std::path::Path, - std::process::Command, - tempfile::{tempdir, TempDir}, -}; - -#[test] -fn test_find_matching_rev_with_lightweight_tag() { - let dir = git_initialize_repo(); - - git_create_commit( - dir.path(), - "foo.js", - b"console.log(\"Hello, world!\");", - "\"initial commit\"", - ); - - let hash = git_create_tag(dir.path(), "1.9.2", false); - - let reference = GitReference::Symbolic("1.9.2"); - let spec = CommitSpec { - repo: String::from("getsentry/sentry-cli"), - path: Some(dir.path().to_path_buf()), - rev: String::from("1.9.2"), - prev_rev: Some(String::from("1.9.1")), +mod tests { + use { + crate::api::RepoProvider, + insta::{assert_debug_snapshot, assert_yaml_snapshot}, + std::fs::File, + std::io::Write as _, + std::path::Path, + std::process::Command, + tempfile::{tempdir, TempDir}, }; - let repos = [Repo { - id: String::from("1"), - name: String::from("getsentry/sentry-cli"), - url: Some(String::from("https://github.com/getsentry/sentry-cli")), - provider: RepoProvider { - id: String::from("integrations:github"), - name: String::from("GitHub"), - }, - status: String::from("active"), - date_created: chrono::Utc::now(), - }]; - - let res_with_lightweight_tag = find_matching_rev(reference, &spec, &repos, false, None); - assert_eq!(res_with_lightweight_tag.unwrap(), Some(hash)); -} + use super::*; -#[test] -fn test_find_matching_rev_with_annotated_tag() { - let dir = git_initialize_repo(); + #[test] + fn test_find_matching_rev_with_lightweight_tag() { + let dir = git_initialize_repo(); - git_create_commit( - dir.path(), - "foo.js", - b"console.log(\"Hello, world!\");", - "\"initial commit\"", - ); + git_create_commit( + dir.path(), + "foo.js", + b"console.log(\"Hello, world!\");", + "\"initial commit\"", + ); - let hash = git_create_tag(dir.path(), "1.9.2-hw", true); + let hash = git_create_tag(dir.path(), "1.9.2", false); - let reference = GitReference::Symbolic("1.9.2-hw"); - let spec = CommitSpec { - repo: String::from("getsentry/sentry-cli"), - path: Some(dir.path().to_path_buf()), - rev: String::from("1.9.2-hw"), - prev_rev: Some(String::from("1.9.1")), - }; + let reference = GitReference::Symbolic("1.9.2"); + let spec = CommitSpec { + repo: String::from("getsentry/sentry-cli"), + path: Some(dir.path().to_path_buf()), + rev: String::from("1.9.2"), + prev_rev: Some(String::from("1.9.1")), + }; - let repos = [Repo { - id: String::from("1"), - name: String::from("getsentry/sentry-cli"), - url: Some(String::from("https://github.com/getsentry/sentry-cli")), - provider: RepoProvider { - id: String::from("integrations:github"), - name: String::from("GitHub"), - }, - status: String::from("active"), - date_created: chrono::Utc::now(), - }]; - - let res_with_annotated_tag = find_matching_rev(reference, &spec, &repos, false, None); - assert_eq!(res_with_annotated_tag.unwrap(), Some(hash)); -} + let repos = [Repo { + id: String::from("1"), + name: String::from("getsentry/sentry-cli"), + url: Some(String::from("https://github.com/getsentry/sentry-cli")), + provider: RepoProvider { + id: String::from("integrations:github"), + name: String::from("GitHub"), + }, + status: String::from("active"), + date_created: chrono::Utc::now(), + }]; + + let res_with_lightweight_tag = find_matching_rev(reference, &spec, &repos, false, None); + assert_eq!(res_with_lightweight_tag.unwrap(), Some(hash)); + } -#[test] -fn test_url_parsing() { - assert_eq!( - VcsUrl::parse("http://github.com/mitsuhiko/flask"), - VcsUrl { - provider: "github.com".into(), - id: "mitsuhiko/flask".into(), - } - ); - assert_eq!( - VcsUrl::parse("git@github.com:mitsuhiko/flask.git"), - VcsUrl { - provider: "github.com".into(), - id: "mitsuhiko/flask".into(), - } - ); - assert_eq!( - VcsUrl::parse("http://bitbucket.org/mitsuhiko/flask"), - VcsUrl { - provider: "bitbucket.org".into(), - id: "mitsuhiko/flask".into(), - } - ); - assert_eq!( - VcsUrl::parse("git@bitbucket.org:mitsuhiko/flask.git"), - VcsUrl { - provider: "bitbucket.org".into(), - id: "mitsuhiko/flask".into(), - } - ); - assert_eq!( - VcsUrl::parse( - "https://bitbucket.example.com/projects/laurynsentry/repos/helloworld/browse" - ), - VcsUrl { - provider: "bitbucket.example.com".into(), - id: "laurynsentry/helloworld".into(), - } - ); - assert_eq!( - VcsUrl::parse("https://neilmanvar.visualstudio.com/_git/sentry-demo"), - VcsUrl { - provider: "neilmanvar.visualstudio.com".into(), - id: "neilmanvar/sentry-demo".into(), - } - ); - assert_eq!( - VcsUrl::parse("https://project@mydomain.visualstudio.com/project/repo/_git"), - VcsUrl { - provider: "mydomain.visualstudio.com".into(), - id: "project/repo".into(), - } - ); - assert_eq!( - VcsUrl::parse("git@ssh.dev.azure.com:v3/project/repo/repo"), - VcsUrl { - provider: "dev.azure.com".into(), - id: "project/repo".into(), - } - ); - assert_eq!( - VcsUrl::parse("git@ssh.dev.azure.com:v3/company/Repo%20Online/Repo%20Online"), - VcsUrl { - provider: "dev.azure.com".into(), - id: "company/repo%20online".into(), - } - ); - assert_eq!( - VcsUrl::parse("https://dev.azure.com/project/repo/_git/repo"), - VcsUrl { - provider: "dev.azure.com".into(), - id: "project/repo".into(), - } - ); - assert_eq!( - VcsUrl::parse("https://dev.azure.com/company/Repo%20Online/_git/Repo%20Online"), - VcsUrl { - provider: "dev.azure.com".into(), - id: "company/repo%20online".into(), - } - ); - assert_eq!( - VcsUrl::parse("https://github.myenterprise.com/mitsuhiko/flask.git"), - VcsUrl { - provider: "github.myenterprise.com".into(), - id: "mitsuhiko/flask".into(), - } - ); - assert_eq!( - VcsUrl::parse("https://gitlab.example.com/gitlab-org/gitlab-ce"), - VcsUrl { - provider: "gitlab.example.com".into(), - id: "gitlab-org/gitlab-ce".into(), - } - ); - assert_eq!( - VcsUrl::parse("git@gitlab.example.com:gitlab-org/gitlab-ce.git"), - VcsUrl { - provider: "gitlab.example.com".into(), - id: "gitlab-org/gitlab-ce".into(), - } - ); - assert_eq!( - VcsUrl::parse("https://gitlab.com/gitlab-org/gitlab-ce"), - VcsUrl { - provider: "gitlab.com".into(), - id: "gitlab-org/gitlab-ce".into(), - } - ); - assert_eq!( - VcsUrl::parse("git@gitlab.com:gitlab-org/gitlab-ce.git"), - VcsUrl { - provider: "gitlab.com".into(), - id: "gitlab-org/gitlab-ce".into(), - } - ); - assert_eq!( - VcsUrl::parse( - "https://source.developers.google.com/p/project-slug/r/github_org-slug_repo-slug" - ), - VcsUrl { - provider: "source.developers.google.com".into(), - id: "org-slug/repo-slug".into(), - } - ); - assert_eq!( - VcsUrl::parse("git@gitlab.com:gitlab-org/GitLab-CE.git"), - VcsUrl { - provider: "gitlab.com".into(), - id: "gitlab-org/gitlab-ce".into(), - } - ); -} + #[test] + fn test_find_matching_rev_with_annotated_tag() { + let dir = git_initialize_repo(); -#[test] -fn test_url_normalization() { - assert!(!is_matching_url( - "http://github.mycompany.com/mitsuhiko/flask", - "git@github.com:mitsuhiko/flask.git" - )); - assert!(!is_matching_url( - "git@github.mycompany.com/mitsuhiko/flask", - "git@github.com:mitsuhiko/flask.git" - )); - assert!(is_matching_url( - "http://github.com/mitsuhiko/flask", - "git@github.com:mitsuhiko/flask.git" - )); - assert!(is_matching_url( - "https://gitlab.com/gitlab-org/gitlab-ce", - "git@gitlab.com:gitlab-org/gitlab-ce.git" - )); - assert!(is_matching_url( - "https://gitlab.example.com/gitlab-org/gitlab-ce", - "git@gitlab.example.com:gitlab-org/gitlab-ce.git" - )); - assert!(is_matching_url( - "https://gitlab.example.com/gitlab-org/GitLab-CE", - "git@gitlab.example.com:gitlab-org/gitlab-ce.git" - )); - assert!(is_matching_url( - "https://gitlab.example.com/gitlab-org/GitLab-CE", - "ssh://git@gitlab.example.com:22/gitlab-org/GitLab-CE" - )); - assert!(is_matching_url( - "git@ssh.dev.azure.com:v3/project/repo/repo", - "https://dev.azure.com/project/repo/_git/repo" - )); - assert!(is_matching_url( - "git@ssh.dev.azure.com:v3/company/Repo%20Online/Repo%20Online", - "https://dev.azure.com/company/Repo%20Online/_git/Repo%20Online" - )); - assert!(is_matching_url( - "git://git@github.com/kamilogorek/picklerick.git", - "https://github.com/kamilogorek/picklerick" - )); - assert!(is_matching_url( - "git+ssh://git@github.com/kamilogorek/picklerick.git", - "https://github.com/kamilogorek/picklerick" - )); - assert!(is_matching_url( - "git+http://git@github.com/kamilogorek/picklerick.git", - "https://github.com/kamilogorek/picklerick" - )); - assert!(is_matching_url( - "git+https://git@github.com/kamilogorek/picklerick.git", - "https://github.com/kamilogorek/picklerick" - )); -} + git_create_commit( + dir.path(), + "foo.js", + b"console.log(\"Hello, world!\");", + "\"initial commit\"", + ); -#[cfg(test)] -fn git_initialize_repo() -> TempDir { - let dir = tempdir().expect("Failed to generate temp dir."); - - Command::new("git") - .args(["init", "--quiet"]) - .current_dir(&dir) - .spawn() - .expect("Failed to execute `git init`.") - .wait() - .expect("Failed to wait on `git init`."); - - Command::new("git") - .args(["branch", "-M", "main"]) - .current_dir(&dir) - .spawn() - .expect("Failed to execute `git branch`.") - .wait() - .expect("Failed to wait on `git branch`."); - - Command::new("git") - .args(["config", "--local", "user.name", "test"]) - .current_dir(&dir) - .spawn() - .expect("Failed to execute `git config`.") - .wait() - .expect("Failed to wait on `git config`."); - - Command::new("git") - .args(["config", "--local", "user.email", "test@example.com"]) - .current_dir(&dir) - .spawn() - .expect("Failed to execute `git config`.") - .wait() - .expect("Failed to wait on `git config`."); - - Command::new("git") - .args([ - "remote", - "add", - "origin", - "https://github.com/getsentry/sentry-cli", - ]) - .current_dir(&dir) - .spawn() - .expect("Failed to execute `git remote add`.") - .wait() - .expect("Failed to wait on `git remote add`."); - - Command::new("git") - .args(["config", "--local", "commit.gpgsign", "false"]) - .current_dir(&dir) - .spawn() - .expect("Failed to execute `config --local commit.gpgsign false`.") - .wait() - .expect("Failed to wait on `config --local commit.gpgsign false`."); - - Command::new("git") - .args(["config", "--local", "tag.gpgsign", "false"]) - .current_dir(&dir) - .spawn() - .expect("Failed to execute `config --local tag.gpgsign false`.") - .wait() - .expect("Failed to wait on `config --local tag.gpgsign false`."); - - dir -} + let hash = git_create_tag(dir.path(), "1.9.2-hw", true); -#[cfg(test)] -fn git_create_commit(dir: &Path, file_path: &str, content: &[u8], commit_message: &str) { - let path = dir.join(file_path); - let mut file = File::create(path).expect("Failed to execute."); - file.write_all(content).expect("Failed to execute."); - - let mut add = Command::new("git") - .args(["add", "-A"]) - .current_dir(dir) - .spawn() - .expect("Failed to execute `git add .`"); - - add.wait().expect("Failed to wait on `git add`."); - - let mut commit = Command::new("git") - .args([ - "commit", - "-am", - commit_message, - "--author", - "John Doe ", - "--quiet", - "--no-edit", - ]) - .current_dir(dir) - .spawn() - .expect("Failed to execute `git commit -m {message}`."); - - commit.wait().expect("Failed to wait on `git commit`."); -} + let reference = GitReference::Symbolic("1.9.2-hw"); + let spec = CommitSpec { + repo: String::from("getsentry/sentry-cli"), + path: Some(dir.path().to_path_buf()), + rev: String::from("1.9.2-hw"), + prev_rev: Some(String::from("1.9.1")), + }; -#[cfg(test)] -fn git_create_tag(dir: &Path, tag_name: &str, annotated: bool) -> String { - let mut tag_cmd = vec!["tag", tag_name]; + let repos = [Repo { + id: String::from("1"), + name: String::from("getsentry/sentry-cli"), + url: Some(String::from("https://github.com/getsentry/sentry-cli")), + provider: RepoProvider { + id: String::from("integrations:github"), + name: String::from("GitHub"), + }, + status: String::from("active"), + date_created: chrono::Utc::now(), + }]; + + let res_with_annotated_tag = find_matching_rev(reference, &spec, &repos, false, None); + assert_eq!(res_with_annotated_tag.unwrap(), Some(hash)); + } - if annotated { - tag_cmd.push("-a"); - tag_cmd.push("-m"); - tag_cmd.push("imannotatedtag"); + #[test] + fn test_url_parsing() { + assert_eq!( + VcsUrl::parse("http://github.com/mitsuhiko/flask"), + VcsUrl { + provider: "github.com".into(), + id: "mitsuhiko/flask".into(), + } + ); + assert_eq!( + VcsUrl::parse("git@github.com:mitsuhiko/flask.git"), + VcsUrl { + provider: "github.com".into(), + id: "mitsuhiko/flask".into(), + } + ); + assert_eq!( + VcsUrl::parse("http://bitbucket.org/mitsuhiko/flask"), + VcsUrl { + provider: "bitbucket.org".into(), + id: "mitsuhiko/flask".into(), + } + ); + assert_eq!( + VcsUrl::parse("git@bitbucket.org:mitsuhiko/flask.git"), + VcsUrl { + provider: "bitbucket.org".into(), + id: "mitsuhiko/flask".into(), + } + ); + assert_eq!( + VcsUrl::parse( + "https://bitbucket.example.com/projects/laurynsentry/repos/helloworld/browse" + ), + VcsUrl { + provider: "bitbucket.example.com".into(), + id: "laurynsentry/helloworld".into(), + } + ); + assert_eq!( + VcsUrl::parse("https://neilmanvar.visualstudio.com/_git/sentry-demo"), + VcsUrl { + provider: "neilmanvar.visualstudio.com".into(), + id: "neilmanvar/sentry-demo".into(), + } + ); + assert_eq!( + VcsUrl::parse("https://project@mydomain.visualstudio.com/project/repo/_git"), + VcsUrl { + provider: "mydomain.visualstudio.com".into(), + id: "project/repo".into(), + } + ); + assert_eq!( + VcsUrl::parse("git@ssh.dev.azure.com:v3/project/repo/repo"), + VcsUrl { + provider: "dev.azure.com".into(), + id: "project/repo".into(), + } + ); + assert_eq!( + VcsUrl::parse("git@ssh.dev.azure.com:v3/company/Repo%20Online/Repo%20Online"), + VcsUrl { + provider: "dev.azure.com".into(), + id: "company/repo%20online".into(), + } + ); + assert_eq!( + VcsUrl::parse("https://dev.azure.com/project/repo/_git/repo"), + VcsUrl { + provider: "dev.azure.com".into(), + id: "project/repo".into(), + } + ); + assert_eq!( + VcsUrl::parse("https://dev.azure.com/company/Repo%20Online/_git/Repo%20Online"), + VcsUrl { + provider: "dev.azure.com".into(), + id: "company/repo%20online".into(), + } + ); + assert_eq!( + VcsUrl::parse("https://github.myenterprise.com/mitsuhiko/flask.git"), + VcsUrl { + provider: "github.myenterprise.com".into(), + id: "mitsuhiko/flask".into(), + } + ); + assert_eq!( + VcsUrl::parse("https://gitlab.example.com/gitlab-org/gitlab-ce"), + VcsUrl { + provider: "gitlab.example.com".into(), + id: "gitlab-org/gitlab-ce".into(), + } + ); + assert_eq!( + VcsUrl::parse("git@gitlab.example.com:gitlab-org/gitlab-ce.git"), + VcsUrl { + provider: "gitlab.example.com".into(), + id: "gitlab-org/gitlab-ce".into(), + } + ); + assert_eq!( + VcsUrl::parse("https://gitlab.com/gitlab-org/gitlab-ce"), + VcsUrl { + provider: "gitlab.com".into(), + id: "gitlab-org/gitlab-ce".into(), + } + ); + assert_eq!( + VcsUrl::parse("git@gitlab.com:gitlab-org/gitlab-ce.git"), + VcsUrl { + provider: "gitlab.com".into(), + id: "gitlab-org/gitlab-ce".into(), + } + ); + assert_eq!( + VcsUrl::parse( + "https://source.developers.google.com/p/project-slug/r/github_org-slug_repo-slug" + ), + VcsUrl { + provider: "source.developers.google.com".into(), + id: "org-slug/repo-slug".into(), + } + ); + assert_eq!( + VcsUrl::parse("git@gitlab.com:gitlab-org/GitLab-CE.git"), + VcsUrl { + provider: "gitlab.com".into(), + id: "gitlab-org/gitlab-ce".into(), + } + ); } - let mut tag = Command::new("git") - .args(tag_cmd) - .current_dir(dir) - .spawn() - .unwrap_or_else(|_| panic!("Failed to execute `git tag {tag_name}`")); + #[test] + fn test_url_normalization() { + assert!(!is_matching_url( + "http://github.mycompany.com/mitsuhiko/flask", + "git@github.com:mitsuhiko/flask.git" + )); + assert!(!is_matching_url( + "git@github.mycompany.com/mitsuhiko/flask", + "git@github.com:mitsuhiko/flask.git" + )); + assert!(is_matching_url( + "http://github.com/mitsuhiko/flask", + "git@github.com:mitsuhiko/flask.git" + )); + assert!(is_matching_url( + "https://gitlab.com/gitlab-org/gitlab-ce", + "git@gitlab.com:gitlab-org/gitlab-ce.git" + )); + assert!(is_matching_url( + "https://gitlab.example.com/gitlab-org/gitlab-ce", + "git@gitlab.example.com:gitlab-org/gitlab-ce.git" + )); + assert!(is_matching_url( + "https://gitlab.example.com/gitlab-org/GitLab-CE", + "git@gitlab.example.com:gitlab-org/gitlab-ce.git" + )); + assert!(is_matching_url( + "https://gitlab.example.com/gitlab-org/GitLab-CE", + "ssh://git@gitlab.example.com:22/gitlab-org/GitLab-CE" + )); + assert!(is_matching_url( + "git@ssh.dev.azure.com:v3/project/repo/repo", + "https://dev.azure.com/project/repo/_git/repo" + )); + assert!(is_matching_url( + "git@ssh.dev.azure.com:v3/company/Repo%20Online/Repo%20Online", + "https://dev.azure.com/company/Repo%20Online/_git/Repo%20Online" + )); + assert!(is_matching_url( + "git://git@github.com/kamilogorek/picklerick.git", + "https://github.com/kamilogorek/picklerick" + )); + assert!(is_matching_url( + "git+ssh://git@github.com/kamilogorek/picklerick.git", + "https://github.com/kamilogorek/picklerick" + )); + assert!(is_matching_url( + "git+http://git@github.com/kamilogorek/picklerick.git", + "https://github.com/kamilogorek/picklerick" + )); + assert!(is_matching_url( + "git+https://git@github.com/kamilogorek/picklerick.git", + "https://github.com/kamilogorek/picklerick" + )); + } - tag.wait().expect("Failed to wait on `git tag`."); + fn git_initialize_repo() -> TempDir { + let dir = tempdir().expect("Failed to generate temp dir."); + + Command::new("git") + .args(["init", "--quiet"]) + .current_dir(&dir) + .spawn() + .expect("Failed to execute `git init`.") + .wait() + .expect("Failed to wait on `git init`."); + + Command::new("git") + .args(["branch", "-M", "main"]) + .current_dir(&dir) + .spawn() + .expect("Failed to execute `git branch`.") + .wait() + .expect("Failed to wait on `git branch`."); + + Command::new("git") + .args(["config", "--local", "user.name", "test"]) + .current_dir(&dir) + .spawn() + .expect("Failed to execute `git config`.") + .wait() + .expect("Failed to wait on `git config`."); + + Command::new("git") + .args(["config", "--local", "user.email", "test@example.com"]) + .current_dir(&dir) + .spawn() + .expect("Failed to execute `git config`.") + .wait() + .expect("Failed to wait on `git config`."); + + Command::new("git") + .args([ + "remote", + "add", + "origin", + "https://github.com/getsentry/sentry-cli", + ]) + .current_dir(&dir) + .spawn() + .expect("Failed to execute `git remote add`.") + .wait() + .expect("Failed to wait on `git remote add`."); + + Command::new("git") + .args(["config", "--local", "commit.gpgsign", "false"]) + .current_dir(&dir) + .spawn() + .expect("Failed to execute `config --local commit.gpgsign false`.") + .wait() + .expect("Failed to wait on `config --local commit.gpgsign false`."); + + Command::new("git") + .args(["config", "--local", "tag.gpgsign", "false"]) + .current_dir(&dir) + .spawn() + .expect("Failed to execute `config --local tag.gpgsign false`.") + .wait() + .expect("Failed to wait on `config --local tag.gpgsign false`."); + + dir + } - let hash = Command::new("git") - .args(["rev-list", "-n", "1", tag_name]) - .current_dir(dir) - .output() - .unwrap_or_else(|_| panic!("Failed to execute `git rev-list -n 1 {tag_name}`.")); + fn git_create_commit(dir: &Path, file_path: &str, content: &[u8], commit_message: &str) { + let path = dir.join(file_path); + let mut file = File::create(path).expect("Failed to execute."); + file.write_all(content).expect("Failed to execute."); + + let mut add = Command::new("git") + .args(["add", "-A"]) + .current_dir(dir) + .spawn() + .expect("Failed to execute `git add .`"); + + add.wait().expect("Failed to wait on `git add`."); + + let mut commit = Command::new("git") + .args([ + "commit", + "-am", + commit_message, + "--author", + "John Doe ", + "--quiet", + "--no-edit", + ]) + .current_dir(dir) + .spawn() + .expect("Failed to execute `git commit -m {message}`."); + + commit.wait().expect("Failed to wait on `git commit`."); + } - String::from_utf8(hash.stdout) - .map(|s| s.trim().to_owned()) - .expect("Invalid utf-8") -} + fn git_create_tag(dir: &Path, tag_name: &str, annotated: bool) -> String { + let mut tag_cmd = vec!["tag", tag_name]; -#[test] -fn test_get_commits_from_git() { - let dir = git_initialize_repo(); + if annotated { + tag_cmd.push("-a"); + tag_cmd.push("-m"); + tag_cmd.push("imannotatedtag"); + } - git_create_commit( - dir.path(), - "foo.js", - b"console.log(\"Hello, world!\");", - "\"initial commit\"", - ); + let mut tag = Command::new("git") + .args(tag_cmd) + .current_dir(dir) + .spawn() + .unwrap_or_else(|_| panic!("Failed to execute `git tag {tag_name}`")); - git_create_commit( - dir.path(), - "foo2.js", - b"console.log(\"Hello, world! Part 2\");", - "\"second commit\"", - ); + tag.wait().expect("Failed to wait on `git tag`."); - let repo = git2::Repository::open(dir.path()).expect("Failed"); - let commits = get_commits_from_git(&repo, "", 20, false).expect("Failed"); - - assert_debug_snapshot!(commits - .0 - .iter() - .map(|c| { - ( - c.author().name().unwrap().to_owned(), - c.author().email().unwrap().to_owned(), - c.summary(), - ) - }) - .collect::>()); -} + let hash = Command::new("git") + .args(["rev-list", "-n", "1", tag_name]) + .current_dir(dir) + .output() + .unwrap_or_else(|_| panic!("Failed to execute `git rev-list -n 1 {tag_name}`.")); -#[test] -fn test_generate_patch_set_base() { - let dir = git_initialize_repo(); + String::from_utf8(hash.stdout) + .map(|s| s.trim().to_owned()) + .expect("Invalid utf-8") + } - git_create_commit( - dir.path(), - "foo.js", - b"console.log(\"Hello, world!\");", - "\"initial commit\"", - ); + #[test] + fn test_get_commits_from_git() { + let dir = git_initialize_repo(); - git_create_commit( - dir.path(), - "foo2.js", - b"console.log(\"Hello, world! Part 2\");", - "\"second commit\"", - ); + git_create_commit( + dir.path(), + "foo.js", + b"console.log(\"Hello, world!\");", + "\"initial commit\"", + ); - git_create_commit( - dir.path(), - "foo2.js", - b"console.log(\"Hello, world! Part 3\");", - "\"third commit\"", - ); + git_create_commit( + dir.path(), + "foo2.js", + b"console.log(\"Hello, world! Part 2\");", + "\"second commit\"", + ); - let repo = git2::Repository::open(dir.path()).expect("Failed"); - let commits = get_commits_from_git(&repo, "", 20, false).expect("Failed"); - let patch_set = - generate_patch_set(&repo, commits.0, commits.1, "example/test-repo").expect("Failed"); + let repo = git2::Repository::open(dir.path()).expect("Failed"); + let commits = get_commits_from_git(&repo, "", 20, false).expect("Failed"); + + assert_debug_snapshot!(commits + .0 + .iter() + .map(|c| { + ( + c.author().name().unwrap().to_owned(), + c.author().email().unwrap().to_owned(), + c.summary(), + ) + }) + .collect::>()); + } - assert_yaml_snapshot!(patch_set, { - ".*.id" => "[id]", - ".*.timestamp" => "[timestamp]" - }); -} + #[test] + fn test_generate_patch_set_base() { + let dir = git_initialize_repo(); -#[test] -fn test_generate_patch_set_previous_commit() { - let dir = git_initialize_repo(); + git_create_commit( + dir.path(), + "foo.js", + b"console.log(\"Hello, world!\");", + "\"initial commit\"", + ); - git_create_commit( - dir.path(), - "foo.js", - b"console.log(\"Hello, world!\");", - "\"initial commit\"", - ); + git_create_commit( + dir.path(), + "foo2.js", + b"console.log(\"Hello, world! Part 2\");", + "\"second commit\"", + ); - git_create_commit( - dir.path(), - "foo2.js", - b"console.log(\"Hello, world! Part 2\");", - "\"second commit\"", - ); + git_create_commit( + dir.path(), + "foo2.js", + b"console.log(\"Hello, world! Part 3\");", + "\"third commit\"", + ); - git_create_commit( - dir.path(), - "foo2.js", - b"console.log(\"Hello, world! Part 3\");", - "\"third commit\"", - ); + let repo = git2::Repository::open(dir.path()).expect("Failed"); + let commits = get_commits_from_git(&repo, "", 20, false).expect("Failed"); + let patch_set = + generate_patch_set(&repo, commits.0, commits.1, "example/test-repo").expect("Failed"); - let repo = git2::Repository::open(dir.path()).expect("Failed"); - let head = repo.revparse_single("HEAD").expect("Failed"); + assert_yaml_snapshot!(patch_set, { + ".*.id" => "[id]", + ".*.timestamp" => "[timestamp]" + }); + } - git_create_commit( - dir.path(), - "foo4.js", - b"console.log(\"Hello, world! Part 4\");", - "\"fourth commit\"", - ); + #[test] + fn test_generate_patch_set_previous_commit() { + let dir = git_initialize_repo(); - git_create_commit( - dir.path(), - "foo2.js", - b"console.log(\"Hello, world! Part 5\");", - "\"fifth commit\"", - ); + git_create_commit( + dir.path(), + "foo.js", + b"console.log(\"Hello, world!\");", + "\"initial commit\"", + ); - let commits = get_commits_from_git(&repo, &head.id().to_string(), 20, false).expect("Failed"); - let patch_set = - generate_patch_set(&repo, commits.0, commits.1, "example/test-repo").expect("Failed"); + git_create_commit( + dir.path(), + "foo2.js", + b"console.log(\"Hello, world! Part 2\");", + "\"second commit\"", + ); - assert_yaml_snapshot!(patch_set, { - ".*.id" => "[id]", - ".*.timestamp" => "[timestamp]" - }); -} + git_create_commit( + dir.path(), + "foo2.js", + b"console.log(\"Hello, world! Part 3\");", + "\"third commit\"", + ); -#[test] -fn test_generate_patch_default_twenty() { - let dir = git_initialize_repo(); + let repo = git2::Repository::open(dir.path()).expect("Failed"); + let head = repo.revparse_single("HEAD").expect("Failed"); - git_create_commit( - dir.path(), - "foo.js", - b"console.log(\"Hello, world!\");", - "\"initial commit\"", - ); + git_create_commit( + dir.path(), + "foo4.js", + b"console.log(\"Hello, world! Part 4\");", + "\"fourth commit\"", + ); - for n in 0..20 { - let file = format!("foo{n}.js"); git_create_commit( dir.path(), - &file, - b"console.log(\"Hello, world! Part 2\");", - "\"another commit\"", + "foo2.js", + b"console.log(\"Hello, world! Part 5\");", + "\"fifth commit\"", ); - } - git_create_commit( - dir.path(), - "foo2.js", - b"console.log(\"Hello, world!\");", - "\"final commit\"", - ); + let commits = + get_commits_from_git(&repo, &head.id().to_string(), 20, false).expect("Failed"); + let patch_set = + generate_patch_set(&repo, commits.0, commits.1, "example/test-repo").expect("Failed"); - let repo = git2::Repository::open(dir.path()).expect("Failed"); - let commits = get_commits_from_git(&repo, "", 20, false).expect("Failed"); - let patch_set = - generate_patch_set(&repo, commits.0, commits.1, "example/test-repo").expect("Failed"); + assert_yaml_snapshot!(patch_set, { + ".*.id" => "[id]", + ".*.timestamp" => "[timestamp]" + }); + } - assert_yaml_snapshot!(patch_set, { - ".*.id" => "[id]", - ".*.timestamp" => "[timestamp]" - }); -} + #[test] + fn test_generate_patch_default_twenty() { + let dir = git_initialize_repo(); -#[test] -fn test_generate_patch_ignore_missing() { - let dir = git_initialize_repo(); + git_create_commit( + dir.path(), + "foo.js", + b"console.log(\"Hello, world!\");", + "\"initial commit\"", + ); - git_create_commit( - dir.path(), - "foo.js", - b"console.log(\"Hello, world!\");", - "\"initial commit\"", - ); + for n in 0..20 { + let file = format!("foo{n}.js"); + git_create_commit( + dir.path(), + &file, + b"console.log(\"Hello, world! Part 2\");", + "\"another commit\"", + ); + } - for n in 0..5 { - let file = format!("foo{n}.js"); git_create_commit( dir.path(), - &file, - b"console.log(\"Hello, world! Part 2\");", - "\"another commit\"", + "foo2.js", + b"console.log(\"Hello, world!\");", + "\"final commit\"", ); + + let repo = git2::Repository::open(dir.path()).expect("Failed"); + let commits = get_commits_from_git(&repo, "", 20, false).expect("Failed"); + let patch_set = + generate_patch_set(&repo, commits.0, commits.1, "example/test-repo").expect("Failed"); + + assert_yaml_snapshot!(patch_set, { + ".*.id" => "[id]", + ".*.timestamp" => "[timestamp]" + }); } - git_create_commit( - dir.path(), - "foo2.js", - b"console.log(\"Hello, world!\");", - "\"final commit\"", - ); + #[test] + fn test_generate_patch_ignore_missing() { + let dir = git_initialize_repo(); - let repo = git2::Repository::open(dir.path()).expect("Failed"); - let commits = get_commits_from_git(&repo, "nonexistinghash", 5, true).expect("Failed"); - let patch_set = - generate_patch_set(&repo, commits.0, commits.1, "example/test-repo").expect("Failed"); + git_create_commit( + dir.path(), + "foo.js", + b"console.log(\"Hello, world!\");", + "\"initial commit\"", + ); - assert_yaml_snapshot!(patch_set, { - ".*.id" => "[id]", - ".*.timestamp" => "[timestamp]" - }); -} + for n in 0..5 { + let file = format!("foo{n}.js"); + git_create_commit( + dir.path(), + &file, + b"console.log(\"Hello, world! Part 2\");", + "\"another commit\"", + ); + } -#[test] -fn test_git_repo_head_ref() { - let dir = git_initialize_repo(); + git_create_commit( + dir.path(), + "foo2.js", + b"console.log(\"Hello, world!\");", + "\"final commit\"", + ); - // Create initial commit - git_create_commit( - dir.path(), - "foo.js", - b"console.log(\"Hello, world!\");", - "\"initial commit\"", - ); + let repo = git2::Repository::open(dir.path()).expect("Failed"); + let commits = get_commits_from_git(&repo, "nonexistinghash", 5, true).expect("Failed"); + let patch_set = + generate_patch_set(&repo, commits.0, commits.1, "example/test-repo").expect("Failed"); - let repo = git2::Repository::open(dir.path()).expect("Failed"); + assert_yaml_snapshot!(patch_set, { + ".*.id" => "[id]", + ".*.timestamp" => "[timestamp]" + }); + } - // Test on a branch (should succeed) - let head_ref = git_repo_head_ref(&repo).expect("Should get branch reference"); - assert_eq!(head_ref, "main"); + #[test] + fn test_git_repo_head_ref() { + let dir = git_initialize_repo(); - // Test in detached HEAD state (should fail) - let head_commit = repo.head().unwrap().target().unwrap(); - repo.set_head_detached(head_commit) - .expect("Failed to detach HEAD"); + // Create initial commit + git_create_commit( + dir.path(), + "foo.js", + b"console.log(\"Hello, world!\");", + "\"initial commit\"", + ); - let head_ref_result = git_repo_head_ref(&repo); - assert!(head_ref_result.is_err()); - assert_eq!( - head_ref_result.unwrap_err().to_string(), - "HEAD is detached - no branch reference available" - ); -} + let repo = git2::Repository::open(dir.path()).expect("Failed"); -#[cfg(test)] -mod tests { - use super::*; + // Test on a branch (should succeed) + let head_ref = git_repo_head_ref(&repo).expect("Should get branch reference"); + assert_eq!(head_ref, "main"); + + // Test in detached HEAD state (should fail) + let head_commit = repo.head().unwrap().target().unwrap(); + repo.set_head_detached(head_commit) + .expect("Failed to detach HEAD"); + + let head_ref_result = git_repo_head_ref(&repo); + assert!(head_ref_result.is_err()); + assert_eq!( + head_ref_result.unwrap_err().to_string(), + "HEAD is detached - no branch reference available" + ); + } #[test] fn test_get_github_pr_number() { diff --git a/src/utils/xcode.rs b/src/utils/xcode.rs index 12dd32900e..2d50f60a4b 100644 --- a/src/utils/xcode.rs +++ b/src/utils/xcode.rs @@ -394,21 +394,26 @@ pub fn launched_from_xcode() -> bool { false } -#[test] -fn test_expansion() { - let mut vars = HashMap::new(); - vars.insert("FOO_BAR".to_owned(), "foo bar baz / blah".to_owned()); - - assert_eq!( - expand_xcodevars("A$(FOO_BAR:rfc1034identifier)B", &vars), - "Afoo-bar-baz-blahB" - ); - assert_eq!( - expand_xcodevars("A$(FOO_BAR:identifier)B", &vars), - "Afoo_bar_baz_blahB" - ); - assert_eq!( - expand_xcodevars("A${FOO_BAR:identifier}B", &vars), - "Afoo_bar_baz_blahB" - ); +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_expansion() { + let mut vars = HashMap::new(); + vars.insert("FOO_BAR".to_owned(), "foo bar baz / blah".to_owned()); + + assert_eq!( + expand_xcodevars("A$(FOO_BAR:rfc1034identifier)B", &vars), + "Afoo-bar-baz-blahB" + ); + assert_eq!( + expand_xcodevars("A$(FOO_BAR:identifier)B", &vars), + "Afoo_bar_baz_blahB" + ); + assert_eq!( + expand_xcodevars("A${FOO_BAR:identifier}B", &vars), + "Afoo_bar_baz_blahB" + ); + } }