aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/tests/repository/vcs/github_driver_test.rs
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-06-25 15:12:06 +0900
committernsfisis <nsfisis@gmail.com>2026-06-26 00:20:05 +0900
commit8117e5450693d19726da877bce8aacf5c7aa53af (patch)
tree4b06e6f6924599f3402d29cdcdeb0f8a88354d89 /crates/shirabe/tests/repository/vcs/github_driver_test.rs
parent8dd3d67884a204ca40e3364206868fea77a312be (diff)
downloadphp-shirabe-8117e5450693d19726da877bce8aacf5c7aa53af.tar.gz
php-shirabe-8117e5450693d19726da877bce8aacf5c7aa53af.tar.zst
php-shirabe-8117e5450693d19726da877bce8aacf5c7aa53af.zip
test: port 44 vcs/downloader/version tests using mock infra
Port git, version_guesser, gitlab_driver, github_driver, and git_downloader tests using the ProcessExecutor/HttpDownloader mocks and IO/Config stubs. Fix production regex-porting bugs surfaced by the now-reachable paths: Url::sanitize and Response::find_header_value had non-delimited PCRE patterns; implement array_search_mixed non-strict branch and a datetime format mapping. Add HttpDownloader::__new_mock so mocked downloaders skip curl construction. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/tests/repository/vcs/github_driver_test.rs')
-rw-r--r--crates/shirabe/tests/repository/vcs/github_driver_test.rs803
1 files changed, 771 insertions, 32 deletions
diff --git a/crates/shirabe/tests/repository/vcs/github_driver_test.rs b/crates/shirabe/tests/repository/vcs/github_driver_test.rs
index f5958a4..0469edf 100644
--- a/crates/shirabe/tests/repository/vcs/github_driver_test.rs
+++ b/crates/shirabe/tests/repository/vcs/github_driver_test.rs
@@ -5,13 +5,22 @@ use std::rc::Rc;
use indexmap::IndexMap;
use shirabe::config::Config;
+use shirabe::config::ConfigSourceInterface;
use shirabe::io::IOInterface;
use shirabe::io::null_io::NullIO;
use shirabe::repository::vcs::GitHubDriver;
use shirabe::util::filesystem::Filesystem;
+use shirabe::util::http_downloader::HttpDownloaderMockHandler;
+use shirabe::util::process_executor::{MockHandler, ProcessExecutor};
use shirabe_php_shim::PhpMixed;
use tempfile::TempDir;
+use crate::http_downloader_mock::{HttpDownloaderMockGuard, expect_full, get_http_downloader_mock};
+use crate::io_stub::IOStub;
+use crate::process_executor_mock::{
+ ProcessExecutorMockGuard, cmd, cmd_full, get_process_executor_mock,
+};
+
struct SetUp {
home: TempDir,
config: Config,
@@ -53,6 +62,82 @@ impl Drop for TearDown {
}
}
+// No-op ConfigSourceInterface, equivalent to PHPUnit's
+// `getMockBuilder(ConfigSourceInterface::class)->getMock()` whose methods all do
+// nothing. Used by testPrivateRepository to satisfy the OAuth token-storing path.
+#[derive(Debug)]
+struct NullConfigSource;
+
+impl ConfigSourceInterface for NullConfigSource {
+ fn add_repository(
+ &mut self,
+ _name: &str,
+ _config: PhpMixed,
+ _append: bool,
+ ) -> anyhow::Result<()> {
+ Ok(())
+ }
+ fn insert_repository(
+ &mut self,
+ _name: &str,
+ _config: PhpMixed,
+ _reference_name: &str,
+ _offset: i64,
+ ) -> anyhow::Result<()> {
+ Ok(())
+ }
+ fn set_repository_url(&mut self, _name: &str, _url: &str) -> anyhow::Result<()> {
+ Ok(())
+ }
+ fn remove_repository(&mut self, _name: &str) -> anyhow::Result<()> {
+ Ok(())
+ }
+ fn add_config_setting(&mut self, _name: &str, _value: PhpMixed) -> anyhow::Result<()> {
+ Ok(())
+ }
+ fn remove_config_setting(&mut self, _name: &str) -> anyhow::Result<()> {
+ Ok(())
+ }
+ fn add_property(&mut self, _name: &str, _value: PhpMixed) -> anyhow::Result<()> {
+ Ok(())
+ }
+ fn remove_property(&mut self, _name: &str) -> anyhow::Result<()> {
+ Ok(())
+ }
+ fn add_link(&mut self, r#type: &str, name: &str, value: &str) -> anyhow::Result<()> {
+ let _ = (r#type, name, value);
+ Ok(())
+ }
+ fn remove_link(&mut self, r#type: &str, name: &str) -> anyhow::Result<()> {
+ let _ = (r#type, name);
+ Ok(())
+ }
+ fn get_name(&self) -> String {
+ String::new()
+ }
+}
+
+// Mirrors PHP's $httpDownloader->expects([...], true): an `['url' => .., 'body' => ..]`
+// entry (status defaults to 200).
+fn http_body(
+ url: &str,
+ body: impl Into<String>,
+) -> shirabe::util::http_downloader::HttpDownloaderMockExpectation {
+ expect_full(url, None, 200, body, vec![String::new()])
+}
+
+// Mirrors PHP's `['url' => .., 'status' => 404]` entry (no body).
+fn http_status(
+ url: &str,
+ status: i64,
+) -> shirabe::util::http_downloader::HttpDownloaderMockExpectation {
+ expect_full(url, None, status, String::new(), vec![String::new()])
+}
+
+fn b64(s: &str) -> String {
+ shirabe_php_shim::base64_encode(s)
+}
+
fn supports_provider() -> Vec<(bool, &'static str)> {
vec![
(false, "https://github.com/acme"),
@@ -80,77 +165,731 @@ fn test_supports() {
}
}
-// The remaining cases construct a GitHubDriver and mock the HttpDownloader/IO to return
-// GitHub API responses; mocking is not available, and a real HttpDownloader reaches
-// curl_multi_init (todo!()).
#[test]
-#[ignore = "HttpDownloaderMock (getHttpDownloaderMock), ProcessExecutorMock, the IOInterface MockObject (askAndHideAnswer/setAuthentication), and setAttribute reflection are not ported"]
fn test_private_repository() {
- let SetUp { home, config: _ } = set_up();
+ let SetUp { home, config } = set_up();
let _tear_down = TearDown::new(home.path().to_path_buf());
- todo!()
+
+ let repo_url = "http://github.com/composer/packagist";
+ let repo_api_url = "https://api.github.com/repos/composer/packagist";
+ let repo_ssh_url = "git@github.com:composer/packagist.git";
+ let identifier = "v0.0.0";
+ let sha = "SOMESHA";
+
+ let config = Rc::new(RefCell::new(config));
+
+ let io: Rc<RefCell<dyn IOInterface>> = Rc::new(RefCell::new(
+ IOStub::new()
+ .with_is_interactive(true)
+ .with_ask_and_hide_answer(Some("sometoken".to_string())),
+ ));
+
+ let (http_downloader, _http_guard): (_, HttpDownloaderMockGuard) = get_http_downloader_mock(
+ vec![
+ http_status(repo_api_url, 404),
+ http_body("https://api.github.com/", "{}"),
+ http_body(
+ repo_api_url,
+ r#"{"master_branch": "test_master", "private": true, "owner": {"login": "composer"}, "name": "packagist"}"#,
+ ),
+ ],
+ true,
+ HttpDownloaderMockHandler::default(),
+ );
+
+ let (process, _process_guard): (_, ProcessExecutorMockGuard) = get_process_executor_mock(
+ vec![],
+ false,
+ MockHandler {
+ r#return: 1,
+ stdout: String::new(),
+ stderr: String::new(),
+ },
+ );
+
+ config
+ .borrow_mut()
+ .set_config_source(Box::new(NullConfigSource));
+ config
+ .borrow_mut()
+ .set_auth_config_source(Box::new(NullConfigSource));
+
+ let mut repo_config: IndexMap<String, PhpMixed> = IndexMap::new();
+ repo_config.insert("url".to_string(), PhpMixed::String(repo_url.to_string()));
+
+ let mut git_hub_driver = GitHubDriver::new(repo_config, io, config, http_downloader, process);
+ git_hub_driver.initialize().unwrap();
+ let mut tags = IndexMap::new();
+ tags.insert(identifier.to_string(), sha.to_string());
+ git_hub_driver.__set_tags(Some(tags));
+
+ assert_eq!("test_master", git_hub_driver.get_root_identifier().unwrap());
+
+ let dist = git_hub_driver.get_dist(sha).unwrap();
+ assert_eq!(Some("zip"), dist.get("type").and_then(|v| v.as_string()));
+ assert_eq!(
+ Some("https://api.github.com/repos/composer/packagist/zipball/SOMESHA"),
+ dist.get("url").and_then(|v| v.as_string())
+ );
+ assert_eq!(
+ Some("SOMESHA"),
+ dist.get("reference").and_then(|v| v.as_string())
+ );
+
+ let source = git_hub_driver.get_source(sha);
+ assert_eq!(Some("git"), source.get("type").and_then(|v| v.as_string()));
+ assert_eq!(
+ Some(repo_ssh_url),
+ source.get("url").and_then(|v| v.as_string())
+ );
+ assert_eq!(
+ Some("SOMESHA"),
+ source.get("reference").and_then(|v| v.as_string())
+ );
}
#[test]
-#[ignore = "HttpDownloaderMock (getHttpDownloaderMock), ProcessExecutorMock, the IOInterface MockObject, and setAttribute reflection are not ported"]
fn test_public_repository() {
- let SetUp { home, config: _ } = set_up();
+ let SetUp { home, config } = set_up();
let _tear_down = TearDown::new(home.path().to_path_buf());
- todo!()
+
+ let repo_url = "http://github.com/composer/packagist";
+ let repo_api_url = "https://api.github.com/repos/composer/packagist";
+ let identifier = "v0.0.0";
+ let sha = "SOMESHA";
+
+ let config = Rc::new(RefCell::new(config));
+ let io: Rc<RefCell<dyn IOInterface>> =
+ Rc::new(RefCell::new(IOStub::new().with_is_interactive(true)));
+
+ let (http_downloader, _http_guard) = get_http_downloader_mock(
+ vec![http_body(
+ repo_api_url,
+ r#"{"master_branch": "test_master", "owner": {"login": "composer"}, "name": "packagist"}"#,
+ )],
+ true,
+ HttpDownloaderMockHandler::default(),
+ );
+
+ let process = Rc::new(RefCell::new(ProcessExecutor::new(None)));
+
+ let mut repo_config: IndexMap<String, PhpMixed> = IndexMap::new();
+ repo_config.insert("url".to_string(), PhpMixed::String(repo_url.to_string()));
+ let repo_url = "https://github.com/composer/packagist.git";
+
+ let mut git_hub_driver = GitHubDriver::new(repo_config, io, config, http_downloader, process);
+ git_hub_driver.initialize().unwrap();
+ let mut tags = IndexMap::new();
+ tags.insert(identifier.to_string(), sha.to_string());
+ git_hub_driver.__set_tags(Some(tags));
+
+ assert_eq!("test_master", git_hub_driver.get_root_identifier().unwrap());
+
+ let dist = git_hub_driver.get_dist(sha).unwrap();
+ assert_eq!(Some("zip"), dist.get("type").and_then(|v| v.as_string()));
+ assert_eq!(
+ Some("https://api.github.com/repos/composer/packagist/zipball/SOMESHA"),
+ dist.get("url").and_then(|v| v.as_string())
+ );
+ assert_eq!(Some(sha), dist.get("reference").and_then(|v| v.as_string()));
+
+ let source = git_hub_driver.get_source(sha);
+ assert_eq!(Some("git"), source.get("type").and_then(|v| v.as_string()));
+ assert_eq!(
+ Some(repo_url),
+ source.get("url").and_then(|v| v.as_string())
+ );
+ assert_eq!(
+ Some(sha),
+ source.get("reference").and_then(|v| v.as_string())
+ );
}
#[test]
-#[ignore = "HttpDownloaderMock (getHttpDownloaderMock), ProcessExecutorMock, the IOInterface MockObject, and setAttribute reflection are not ported"]
+#[ignore = "blocked by shim: getComposerInformation -> get_change_date -> shirabe_php_shim::date_create is todo!()"]
fn test_public_repository2() {
- let SetUp { home, config: _ } = set_up();
+ let SetUp { home, config } = set_up();
let _tear_down = TearDown::new(home.path().to_path_buf());
- todo!()
+
+ let repo_url = "http://github.com/composer/packagist";
+ let repo_api_url = "https://api.github.com/repos/composer/packagist";
+ let identifier = "feature/3.2-foo";
+ let sha = "SOMESHA";
+
+ let config = Rc::new(RefCell::new(config));
+ let io: Rc<RefCell<dyn IOInterface>> =
+ Rc::new(RefCell::new(IOStub::new().with_is_interactive(true)));
+
+ let (http_downloader, _http_guard) = get_http_downloader_mock(
+ vec![
+ http_body(
+ repo_api_url,
+ r#"{"master_branch": "test_master", "owner": {"login": "composer"}, "name": "packagist"}"#,
+ ),
+ http_body(
+ "https://api.github.com/repos/composer/packagist/contents/composer.json?ref=feature%2F3.2-foo",
+ format!(
+ r#"{{"encoding":"base64","content":"{}"}}"#,
+ b64(&format!(r#"{{"support": {{"source": "{}" }}}}"#, repo_url))
+ ),
+ ),
+ http_body(
+ "https://api.github.com/repos/composer/packagist/commits/feature%2F3.2-foo",
+ r#"{"commit": {"committer":{ "date": "2012-09-10"}}}"#,
+ ),
+ http_body(
+ "https://api.github.com/repos/composer/packagist/contents/.github/FUNDING.yml",
+ format!(
+ r#"{{"encoding": "base64", "content": "{}"}}"#,
+ b64("custom: https://example.com")
+ ),
+ ),
+ ],
+ true,
+ HttpDownloaderMockHandler::default(),
+ );
+
+ let process = Rc::new(RefCell::new(ProcessExecutor::new(None)));
+
+ let mut repo_config: IndexMap<String, PhpMixed> = IndexMap::new();
+ repo_config.insert("url".to_string(), PhpMixed::String(repo_url.to_string()));
+ let repo_url = "https://github.com/composer/packagist.git";
+
+ let mut git_hub_driver = GitHubDriver::new(repo_config, io, config, http_downloader, process);
+ git_hub_driver.initialize().unwrap();
+ let mut tags = IndexMap::new();
+ tags.insert(identifier.to_string(), sha.to_string());
+ git_hub_driver.__set_tags(Some(tags));
+
+ assert_eq!("test_master", git_hub_driver.get_root_identifier().unwrap());
+
+ let dist = git_hub_driver.get_dist(sha).unwrap();
+ assert_eq!(Some("zip"), dist.get("type").and_then(|v| v.as_string()));
+ assert_eq!(
+ Some("https://api.github.com/repos/composer/packagist/zipball/SOMESHA"),
+ dist.get("url").and_then(|v| v.as_string())
+ );
+ assert_eq!(Some(sha), dist.get("reference").and_then(|v| v.as_string()));
+
+ let source = git_hub_driver.get_source(sha);
+ assert_eq!(Some("git"), source.get("type").and_then(|v| v.as_string()));
+ assert_eq!(
+ Some(repo_url),
+ source.get("url").and_then(|v| v.as_string())
+ );
+ assert_eq!(
+ Some(sha),
+ source.get("reference").and_then(|v| v.as_string())
+ );
+
+ let data = git_hub_driver
+ .get_composer_information(identifier)
+ .unwrap()
+ .unwrap();
+ assert!(!data.contains_key("abandoned"));
}
#[test]
-#[ignore = "HttpDownloaderMock (getHttpDownloaderMock), ProcessExecutorMock, the IOInterface MockObject, and setAttribute reflection are not ported"]
+#[ignore = "blocked by shim: getComposerInformation -> get_change_date -> shirabe_php_shim::date_create is todo!()"]
fn test_invalid_support_data() {
- let SetUp { home, config: _ } = set_up();
+ let SetUp { home, config } = set_up();
let _tear_down = TearDown::new(home.path().to_path_buf());
- todo!()
+
+ let repo_url = "http://github.com/composer/packagist";
+ let repo_api_url = "https://api.github.com/repos/composer/packagist";
+ let identifier = "feature/3.2-foo";
+ let sha = "SOMESHA";
+
+ let config = Rc::new(RefCell::new(config));
+ let io: Rc<RefCell<dyn IOInterface>> =
+ Rc::new(RefCell::new(IOStub::new().with_is_interactive(true)));
+
+ let (http_downloader, _http_guard) = get_http_downloader_mock(
+ vec![
+ http_body(
+ repo_api_url,
+ r#"{"master_branch": "test_master", "owner": {"login": "composer"}, "name": "packagist"}"#,
+ ),
+ http_body(
+ "https://api.github.com/repos/composer/packagist/contents/composer.json?ref=feature%2F3.2-foo",
+ format!(
+ r#"{{"encoding":"base64","content":"{}"}}"#,
+ b64(&format!(r#"{{"support": "{}" }}"#, repo_url))
+ ),
+ ),
+ http_body(
+ "https://api.github.com/repos/composer/packagist/commits/feature%2F3.2-foo",
+ r#"{"commit": {"committer":{ "date": "2012-09-10"}}}"#,
+ ),
+ http_body(
+ "https://api.github.com/repos/composer/packagist/contents/.github/FUNDING.yml",
+ format!(
+ r#"{{"encoding": "base64", "content": "{}"}}"#,
+ b64("custom: https://example.com")
+ ),
+ ),
+ ],
+ true,
+ HttpDownloaderMockHandler::default(),
+ );
+
+ let process = Rc::new(RefCell::new(ProcessExecutor::new(None)));
+
+ let mut repo_config: IndexMap<String, PhpMixed> = IndexMap::new();
+ repo_config.insert("url".to_string(), PhpMixed::String(repo_url.to_string()));
+
+ let mut git_hub_driver = GitHubDriver::new(repo_config, io, config, http_downloader, process);
+ git_hub_driver.initialize().unwrap();
+ let mut tags = IndexMap::new();
+ tags.insert(identifier.to_string(), sha.to_string());
+ git_hub_driver.__set_tags(Some(tags));
+ let mut branches = IndexMap::new();
+ branches.insert("test_master".to_string(), sha.to_string());
+ git_hub_driver.__set_branches(Some(branches));
+
+ let data = git_hub_driver
+ .get_composer_information(identifier)
+ .unwrap()
+ .unwrap();
+
+ let support = data.get("support").and_then(|v| v.as_array()).unwrap();
+ assert_eq!(
+ Some("https://github.com/composer/packagist/tree/feature/3.2-foo"),
+ support.get("source").and_then(|v| v.as_string())
+ );
+}
+
+fn funding_url_provider() -> Vec<(&'static str, Option<Vec<(&'static str, &'static str)>>)> {
+ let all_named_platforms = "community_bridge: project-name
+github: [userA, userB]
+issuehunt: userName
+ko_fi: userName
+liberapay: userName
+open_collective: userName
+patreon: userName
+tidelift: Platform/Package
+polar: userName
+buy_me_a_coffee: userName
+thanks_dev: u/gh/userName
+otechie: userName";
+
+ vec![
+ (
+ all_named_platforms,
+ Some(vec![
+ (
+ "community_bridge",
+ "https://funding.communitybridge.org/projects/project-name",
+ ),
+ ("github", "https://github.com/userA"),
+ ("github", "https://github.com/userB"),
+ ("issuehunt", "https://issuehunt.io/r/userName"),
+ ("ko_fi", "https://ko-fi.com/userName"),
+ ("liberapay", "https://liberapay.com/userName"),
+ ("open_collective", "https://opencollective.com/userName"),
+ ("patreon", "https://www.patreon.com/userName"),
+ (
+ "tidelift",
+ "https://tidelift.com/funding/github/Platform/Package",
+ ),
+ ("polar", "https://polar.sh/userName"),
+ ("buy_me_a_coffee", "https://www.buymeacoffee.com/userName"),
+ ("thanks_dev", "https://thanks.dev/u/gh/userName"),
+ ("otechie", "https://otechie.com/userName"),
+ ]),
+ ),
+ (
+ "custom: example.com",
+ Some(vec![("custom", "https://example.com")]),
+ ),
+ (
+ "custom: [example.com]",
+ Some(vec![("custom", "https://example.com")]),
+ ),
+ (
+ "custom: \"https://example.com\"",
+ Some(vec![("custom", "https://example.com")]),
+ ),
+ (
+ "custom: [\"https://example.com\"]",
+ Some(vec![("custom", "https://example.com")]),
+ ),
+ (
+ "custom: [\"https://example.com\", example.org]",
+ Some(vec![
+ ("custom", "https://example.com"),
+ ("custom", "https://example.org"),
+ ]),
+ ),
+ (
+ "custom: [example.net/funding, \"https://example.com\", example.org]",
+ Some(vec![
+ ("custom", "https://example.com"),
+ ("custom", "https://example.org"),
+ ]),
+ ),
+ ]
}
#[test]
-#[ignore = "HttpDownloaderMock (getHttpDownloaderMock), ProcessExecutorMock, the IOInterface MockObject, setAttribute reflection, and the fundingUrlProvider data provider are not ported"]
+#[ignore = "blocked by shim: getComposerInformation -> get_change_date -> shirabe_php_shim::date_create is todo!()"]
fn test_funding_format() {
- let SetUp { home, config: _ } = set_up();
- let _tear_down = TearDown::new(home.path().to_path_buf());
- todo!()
+ for (funding, expected) in funding_url_provider() {
+ let SetUp { home, config } = set_up();
+ let _tear_down = TearDown::new(home.path().to_path_buf());
+
+ let repo_url = "http://github.com/composer/packagist";
+ let repo_api_url = "https://api.github.com/repos/composer/packagist";
+ let identifier = "feature/3.2-foo";
+ let sha = "SOMESHA";
+
+ let config = Rc::new(RefCell::new(config));
+ let io: Rc<RefCell<dyn IOInterface>> =
+ Rc::new(RefCell::new(IOStub::new().with_is_interactive(true)));
+
+ let (http_downloader, _http_guard) = get_http_downloader_mock(
+ vec![
+ http_body(
+ repo_api_url,
+ r#"{"master_branch": "test_master", "owner": {"login": "composer"}, "name": "packagist"}"#,
+ ),
+ http_body(
+ "https://api.github.com/repos/composer/packagist/contents/composer.json?ref=feature%2F3.2-foo",
+ format!(
+ r#"{{"encoding":"base64","content":"{}"}}"#,
+ b64(&format!(r#"{{"support": {{"source": "{}" }}}}"#, repo_url))
+ ),
+ ),
+ http_body(
+ "https://api.github.com/repos/composer/packagist/commits/feature%2F3.2-foo",
+ r#"{"commit": {"committer":{ "date": "2012-09-10"}}}"#,
+ ),
+ http_body(
+ "https://api.github.com/repos/composer/packagist/contents/.github/FUNDING.yml",
+ format!(r#"{{"encoding": "base64", "content": "{}"}}"#, b64(funding)),
+ ),
+ ],
+ true,
+ HttpDownloaderMockHandler::default(),
+ );
+
+ let process = Rc::new(RefCell::new(ProcessExecutor::new(None)));
+
+ let mut repo_config: IndexMap<String, PhpMixed> = IndexMap::new();
+ repo_config.insert("url".to_string(), PhpMixed::String(repo_url.to_string()));
+
+ let mut git_hub_driver =
+ GitHubDriver::new(repo_config, io, config, http_downloader, process);
+ git_hub_driver.initialize().unwrap();
+ let mut tags = IndexMap::new();
+ tags.insert(identifier.to_string(), sha.to_string());
+ git_hub_driver.__set_tags(Some(tags));
+ let mut branches = IndexMap::new();
+ branches.insert("test_master".to_string(), sha.to_string());
+ git_hub_driver.__set_branches(Some(branches));
+
+ let data = git_hub_driver
+ .get_composer_information(identifier)
+ .unwrap()
+ .unwrap();
+
+ match expected {
+ None => assert!(!data.contains_key("funding")),
+ Some(expected) => {
+ let funding_list = match data.get("funding") {
+ Some(PhpMixed::List(l)) => l.clone(),
+ Some(PhpMixed::Array(m)) => m.values().cloned().collect(),
+ other => panic!("unexpected funding value: {:?}", other),
+ };
+ let actual: Vec<(String, String)> = funding_list
+ .iter()
+ .map(|entry| {
+ let m = entry.as_array().unwrap();
+ (
+ m.get("type")
+ .and_then(|v| v.as_string())
+ .unwrap_or("")
+ .to_string(),
+ m.get("url")
+ .and_then(|v| v.as_string())
+ .unwrap_or("")
+ .to_string(),
+ )
+ })
+ .collect();
+ let expected_vec: Vec<(String, String)> = expected
+ .iter()
+ .map(|(t, u)| (t.to_string(), u.to_string()))
+ .collect();
+ assert_eq!(expected_vec, actual);
+ }
+ }
+ }
}
#[test]
-#[ignore = "HttpDownloaderMock (getHttpDownloaderMock), ProcessExecutorMock, the IOInterface MockObject, and setAttribute reflection are not ported"]
+#[ignore = "blocked by shim: getComposerInformation -> get_change_date -> shirabe_php_shim::date_create is todo!()"]
fn test_public_repository_archived() {
- let SetUp { home, config: _ } = set_up();
+ let SetUp { home, config } = set_up();
let _tear_down = TearDown::new(home.path().to_path_buf());
- todo!()
+
+ let repo_url = "http://github.com/composer/packagist";
+ let repo_api_url = "https://api.github.com/repos/composer/packagist";
+ let identifier = "v0.0.0";
+ let sha = "SOMESHA";
+ let composer_json_url = format!(
+ "https://api.github.com/repos/composer/packagist/contents/composer.json?ref={}",
+ sha
+ );
+
+ let config = Rc::new(RefCell::new(config));
+ let io: Rc<RefCell<dyn IOInterface>> =
+ Rc::new(RefCell::new(IOStub::new().with_is_interactive(true)));
+
+ let (http_downloader, _http_guard) = get_http_downloader_mock(
+ vec![
+ http_body(
+ repo_api_url,
+ r#"{"master_branch": "test_master", "owner": {"login": "composer"}, "name": "packagist", "archived": true}"#,
+ ),
+ http_body(
+ &composer_json_url,
+ format!(
+ r#"{{"encoding": "base64", "content": "{}"}}"#,
+ b64(r#"{"name": "composer/packagist"}"#)
+ ),
+ ),
+ http_body(
+ &format!(
+ "https://api.github.com/repos/composer/packagist/commits/{}",
+ sha
+ ),
+ r#"{"commit": {"committer":{ "date": "2012-09-10"}}}"#,
+ ),
+ http_body(
+ "https://api.github.com/repos/composer/packagist/contents/.github/FUNDING.yml",
+ format!(
+ r#"{{"encoding": "base64", "content": "{}"}}"#,
+ b64("custom: https://example.com")
+ ),
+ ),
+ ],
+ true,
+ HttpDownloaderMockHandler::default(),
+ );
+
+ let process = Rc::new(RefCell::new(ProcessExecutor::new(None)));
+
+ let mut repo_config: IndexMap<String, PhpMixed> = IndexMap::new();
+ repo_config.insert("url".to_string(), PhpMixed::String(repo_url.to_string()));
+
+ let mut git_hub_driver = GitHubDriver::new(repo_config, io, config, http_downloader, process);
+ git_hub_driver.initialize().unwrap();
+ let mut tags = IndexMap::new();
+ tags.insert(identifier.to_string(), sha.to_string());
+ git_hub_driver.__set_tags(Some(tags));
+
+ let data = git_hub_driver
+ .get_composer_information(sha)
+ .unwrap()
+ .unwrap();
+
+ assert_eq!(Some(true), data.get("abandoned").and_then(|v| v.as_bool()));
}
#[test]
-#[ignore = "HttpDownloaderMock (getHttpDownloaderMock), ProcessExecutorMock, and the IOInterface MockObject are not ported"]
+#[ignore = "GitDriver clone-fallback path runs an unexpected `git --version` (Git::get_version) not in the PHP mock expectation list; needs the version static seeded and the Rust sync_mirror command sequence to match"]
fn test_private_repository_no_interaction() {
- let SetUp { home, config: _ } = set_up();
+ let SetUp { home, config } = set_up();
let _tear_down = TearDown::new(home.path().to_path_buf());
- todo!()
+
+ let repo_url = "http://github.com/composer/packagist";
+ let repo_api_url = "https://api.github.com/repos/composer/packagist";
+ let repo_ssh_url = "git@github.com:composer/packagist.git";
+ let identifier = "v0.0.0";
+ let sha = "SOMESHA";
+
+ let config = Rc::new(RefCell::new(config));
+ let io: Rc<RefCell<dyn IOInterface>> =
+ Rc::new(RefCell::new(IOStub::new().with_is_interactive(false)));
+
+ let (http_downloader, _http_guard) = get_http_downloader_mock(
+ vec![http_status(repo_api_url, 404)],
+ true,
+ HttpDownloaderMockHandler::default(),
+ );
+
+ // clean local clone if present
+ let cache_dir = std::env::temp_dir().join("composer-test");
+ let mut fs = Filesystem::new(None);
+ let _ = fs.remove_directory(&cache_dir);
+ let cache_vcs_dir = std::env::temp_dir()
+ .join("composer-test/cache")
+ .to_string_lossy()
+ .into_owned();
+ {
+ let mut top: IndexMap<String, PhpMixed> = IndexMap::new();
+ let mut config_section: IndexMap<String, PhpMixed> = IndexMap::new();
+ config_section.insert(
+ "cache-vcs-dir".to_string(),
+ PhpMixed::String(cache_vcs_dir.clone()),
+ );
+ top.insert("config".to_string(), PhpMixed::Array(config_section));
+ config.borrow_mut().merge(&top, Config::SOURCE_UNKNOWN);
+ }
+ let resolved_cache_vcs_dir = config
+ .borrow_mut()
+ .get("cache-vcs-dir")
+ .as_string()
+ .unwrap_or("")
+ .to_string();
+
+ let (process, _process_guard): (_, ProcessExecutorMockGuard) = get_process_executor_mock(
+ vec![
+ cmd_full(["git", "config", "github.accesstoken"], 1, "", ""),
+ cmd([
+ "git",
+ "clone",
+ "--mirror",
+ "--",
+ repo_ssh_url,
+ &format!(
+ "{}/git-github.com-composer-packagist.git/",
+ resolved_cache_vcs_dir
+ ),
+ ]),
+ cmd(["git", "remote", "-v"]),
+ cmd(["git", "remote", "set-url", "origin", "--", repo_ssh_url]),
+ cmd_full(
+ ["git", "show-ref", "--tags", "--dereference"],
+ 0,
+ format!("{} refs/tags/{}", sha, identifier),
+ "",
+ ),
+ cmd_full(
+ ["git", "branch", "--no-color", "--no-abbrev", "-v"],
+ 0,
+ " test_master edf93f1fccaebd8764383dc12016d0a1a9672d89 Fix test & behavior",
+ "",
+ ),
+ cmd_full(["git", "branch", "--no-color"], 0, "* test_master", ""),
+ ],
+ true,
+ MockHandler::default(),
+ );
+
+ let mut repo_config: IndexMap<String, PhpMixed> = IndexMap::new();
+ repo_config.insert("url".to_string(), PhpMixed::String(repo_url.to_string()));
+
+ let mut git_hub_driver = GitHubDriver::new(repo_config, io, config, http_downloader, process);
+ git_hub_driver.initialize().unwrap();
+
+ assert_eq!("test_master", git_hub_driver.get_root_identifier().unwrap());
+
+ let dist = git_hub_driver.get_dist(sha).unwrap();
+ assert_eq!(Some("zip"), dist.get("type").and_then(|v| v.as_string()));
+ assert_eq!(
+ Some("https://api.github.com/repos/composer/packagist/zipball/SOMESHA"),
+ dist.get("url").and_then(|v| v.as_string())
+ );
+ assert_eq!(Some(sha), dist.get("reference").and_then(|v| v.as_string()));
+
+ let source = git_hub_driver.get_source(identifier);
+ assert_eq!(Some("git"), source.get("type").and_then(|v| v.as_string()));
+ assert_eq!(
+ Some(repo_ssh_url),
+ source.get("url").and_then(|v| v.as_string())
+ );
+ assert_eq!(
+ Some(identifier),
+ source.get("reference").and_then(|v| v.as_string())
+ );
+
+ let source = git_hub_driver.get_source(sha);
+ assert_eq!(Some("git"), source.get("type").and_then(|v| v.as_string()));
+ assert_eq!(
+ Some(repo_ssh_url),
+ source.get("url").and_then(|v| v.as_string())
+ );
+ assert_eq!(
+ Some(sha),
+ source.get("reference").and_then(|v| v.as_string())
+ );
+}
+
+fn invalid_url_provider() -> Vec<&'static str> {
+ vec![
+ "https://github.com/acme",
+ "https://github.com/acme/repository/releases",
+ "https://github.com/acme/repository/pulls",
+ ]
}
#[test]
-#[ignore = "IOInterface MockObject (getMockBuilder) and HttpDownloader MockObject (getMockBuilder) plus the invalidUrlProvider data provider are not ported"]
fn test_initialize_invalid_repo_url() {
- let SetUp { home, config: _ } = set_up();
- let _tear_down = TearDown::new(home.path().to_path_buf());
- todo!()
+ for url in invalid_url_provider() {
+ let SetUp { home, config } = set_up();
+ let _tear_down = TearDown::new(home.path().to_path_buf());
+
+ let config = Rc::new(RefCell::new(config));
+ let io: Rc<RefCell<dyn IOInterface>> = Rc::new(RefCell::new(IOStub::new()));
+
+ let (http_downloader, _http_guard) =
+ get_http_downloader_mock(vec![], true, HttpDownloaderMockHandler::default());
+ let process = Rc::new(RefCell::new(ProcessExecutor::new(None)));
+
+ let mut repo_config: IndexMap<String, PhpMixed> = IndexMap::new();
+ repo_config.insert("url".to_string(), PhpMixed::String(url.to_string()));
+
+ let mut git_hub_driver =
+ GitHubDriver::new(repo_config, io, config, http_downloader, process);
+ let result = git_hub_driver.initialize();
+ assert!(
+ result.is_err(),
+ "expected InvalidArgumentException for url {}",
+ url
+ );
+ }
}
#[test]
-#[ignore = "HttpDownloaderMock (getHttpDownloaderMock), ProcessExecutorMock, and the IOInterface MockObject are not ported"]
fn test_get_empty_file_content() {
- let SetUp { home, config: _ } = set_up();
+ let SetUp { home, config } = set_up();
let _tear_down = TearDown::new(home.path().to_path_buf());
- todo!()
+
+ let repo_url = "http://github.com/composer/packagist";
+
+ let config = Rc::new(RefCell::new(config));
+ let io: Rc<RefCell<dyn IOInterface>> =
+ Rc::new(RefCell::new(IOStub::new().with_is_interactive(true)));
+
+ let (http_downloader, _http_guard) = get_http_downloader_mock(
+ vec![
+ http_body(
+ "https://api.github.com/repos/composer/packagist",
+ r#"{"master_branch": "test_master", "owner": {"login": "composer"}, "name": "packagist", "archived": true}"#,
+ ),
+ http_body(
+ "https://api.github.com/repos/composer/packagist/contents/composer.json?ref=main",
+ r#"{"encoding":"base64","content":""}"#,
+ ),
+ ],
+ true,
+ HttpDownloaderMockHandler::default(),
+ );
+
+ let process = Rc::new(RefCell::new(ProcessExecutor::new(None)));
+
+ let mut repo_config: IndexMap<String, PhpMixed> = IndexMap::new();
+ repo_config.insert("url".to_string(), PhpMixed::String(repo_url.to_string()));
+
+ let mut git_hub_driver = GitHubDriver::new(repo_config, io, config, http_downloader, process);
+ git_hub_driver.initialize().unwrap();
+
+ assert_eq!(
+ Some(String::new()),
+ git_hub_driver
+ .get_file_content("composer.json", "main")
+ .unwrap()
+ );
}