aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/tests/util
diff options
context:
space:
mode:
Diffstat (limited to 'crates/shirabe/tests/util')
-rw-r--r--crates/shirabe/tests/util/auth_helper_test.rs133
-rw-r--r--crates/shirabe/tests/util/bitbucket_test.rs199
-rw-r--r--crates/shirabe/tests/util/forgejo_test.rs123
-rw-r--r--crates/shirabe/tests/util/github_test.rs123
-rw-r--r--crates/shirabe/tests/util/gitlab_test.rs77
5 files changed, 244 insertions, 411 deletions
diff --git a/crates/shirabe/tests/util/auth_helper_test.rs b/crates/shirabe/tests/util/auth_helper_test.rs
index b760fc8..7738afb 100644
--- a/crates/shirabe/tests/util/auth_helper_test.rs
+++ b/crates/shirabe/tests/util/auth_helper_test.rs
@@ -399,59 +399,23 @@ fn test_is_public_bit_bucket_download_with_non_bitbucket_public_url() {
);
}
-// Records addConfigSetting calls and serves a configurable getName, mirroring the
-// PHPUnit mock of ConfigSourceInterface used by the storeAuth tests.
-#[derive(Debug)]
-struct ConfigSourceMock {
- name: String,
- added: Rc<RefCell<Vec<(String, PhpMixed)>>>,
-}
-
-impl ConfigSourceInterface for ConfigSourceMock {
- fn add_repository(
- &mut self,
- _name: &str,
- _config: PhpMixed,
- _append: bool,
- ) -> anyhow::Result<()> {
- unreachable!()
- }
- fn insert_repository(
- &mut self,
- _name: &str,
- _config: PhpMixed,
- _reference_name: &str,
- _offset: i64,
- ) -> anyhow::Result<()> {
- unreachable!()
- }
- fn set_repository_url(&mut self, _name: &str, _url: &str) -> anyhow::Result<()> {
- unreachable!()
- }
- fn remove_repository(&mut self, _name: &str) -> anyhow::Result<()> {
- unreachable!()
- }
- fn add_config_setting(&mut self, name: &str, value: PhpMixed) -> anyhow::Result<()> {
- self.added.borrow_mut().push((name.to_string(), value));
- Ok(())
- }
- fn remove_config_setting(&mut self, _name: &str) -> anyhow::Result<()> {
- unreachable!()
- }
- fn add_property(&mut self, _name: &str, _value: PhpMixed) -> anyhow::Result<()> {
- unreachable!()
- }
- fn remove_property(&mut self, _name: &str) -> anyhow::Result<()> {
- unreachable!()
- }
- fn add_link(&mut self, _type: &str, _name: &str, _value: &str) -> anyhow::Result<()> {
- unreachable!()
- }
- fn remove_link(&mut self, _type: &str, _name: &str) -> anyhow::Result<()> {
- unreachable!()
- }
- fn get_name(&self) -> String {
- self.name.clone()
+// Mirrors the PHPUnit mock of ConfigSourceInterface used by the storeAuth tests.
+// Methods left without an expectation panic if called.
+mockall::mock! {
+ #[derive(Debug)]
+ pub ConfigSource {}
+ impl ConfigSourceInterface for ConfigSource {
+ fn add_repository(&mut self, name: &str, config: PhpMixed, append: bool) -> anyhow::Result<()>;
+ fn insert_repository(&mut self, name: &str, config: PhpMixed, reference_name: &str, offset: i64) -> anyhow::Result<()>;
+ fn set_repository_url(&mut self, name: &str, url: &str) -> anyhow::Result<()>;
+ fn remove_repository(&mut self, name: &str) -> anyhow::Result<()>;
+ fn add_config_setting(&mut self, name: &str, value: PhpMixed) -> anyhow::Result<()>;
+ fn remove_config_setting(&mut self, name: &str) -> anyhow::Result<()>;
+ fn add_property(&mut self, name: &str, value: PhpMixed) -> anyhow::Result<()>;
+ fn remove_property(&mut self, name: &str) -> anyhow::Result<()>;
+ fn add_link(&mut self, r#type: &str, name: &str, value: &str) -> anyhow::Result<()>;
+ fn remove_link(&mut self, r#type: &str, name: &str) -> anyhow::Result<()>;
+ fn get_name(&self) -> String;
}
}
@@ -474,25 +438,23 @@ fn test_store_auth_automatically() {
let origin = "github.com";
expects_authentication(&f.io, origin, "my_username", "my_password");
- let added = Rc::new(RefCell::new(Vec::new()));
+ let mut source = MockConfigSource::new();
+ source
+ .expect_get_name()
+ .returning(|| "https://api.gitlab.com/source".to_string());
+ let expected = expected_auth_setting("my_username", "my_password");
+ source
+ .expect_add_config_setting()
+ .times(1)
+ .withf(move |name, value| name == "http-basic.github.com" && *value == expected)
+ .returning(|_, _| Ok(()));
f.config
.borrow_mut()
- .set_auth_config_source(Box::new(ConfigSourceMock {
- name: "https://api.gitlab.com/source".to_string(),
- added: added.clone(),
- }));
+ .set_auth_config_source(Box::new(source));
f.auth_helper
.store_auth(origin, StoreAuth::Bool(true))
.unwrap();
-
- assert_eq!(
- *added.borrow(),
- vec![(
- "http-basic.github.com".to_string(),
- expected_auth_setting("my_username", "my_password"),
- )]
- );
}
#[test]
@@ -515,23 +477,22 @@ fn test_store_auth_with_prompt_yes_answer() {
)
.unwrap();
- let added = Rc::new(RefCell::new(Vec::new()));
+ let mut source = MockConfigSource::new();
+ source
+ .expect_get_name()
+ .times(1)
+ .returning(move || config_source_name.to_string());
+ let expected = expected_auth_setting("my_username", "my_password");
+ source
+ .expect_add_config_setting()
+ .times(1)
+ .withf(move |name, value| name == "http-basic.github.com" && *value == expected)
+ .returning(|_, _| Ok(()));
f.config
.borrow_mut()
- .set_auth_config_source(Box::new(ConfigSourceMock {
- name: config_source_name.to_string(),
- added: added.clone(),
- }));
+ .set_auth_config_source(Box::new(source));
f.auth_helper.store_auth(origin, StoreAuth::Prompt).unwrap();
-
- assert_eq!(
- *added.borrow(),
- vec![(
- "http-basic.github.com".to_string(),
- expected_auth_setting("my_username", "my_password"),
- )]
- );
}
#[test]
@@ -553,17 +514,17 @@ fn test_store_auth_with_prompt_no_answer() {
)
.unwrap();
- let added = Rc::new(RefCell::new(Vec::new()));
+ let mut source = MockConfigSource::new();
+ source
+ .expect_get_name()
+ .times(1)
+ .returning(move || config_source_name.to_string());
+ source.expect_add_config_setting().times(0);
f.config
.borrow_mut()
- .set_auth_config_source(Box::new(ConfigSourceMock {
- name: config_source_name.to_string(),
- added: added.clone(),
- }));
+ .set_auth_config_source(Box::new(source));
f.auth_helper.store_auth(origin, StoreAuth::Prompt).unwrap();
-
- assert!(added.borrow().is_empty());
}
#[test]
diff --git a/crates/shirabe/tests/util/bitbucket_test.rs b/crates/shirabe/tests/util/bitbucket_test.rs
index d57a49a..2817266 100644
--- a/crates/shirabe/tests/util/bitbucket_test.rs
+++ b/crates/shirabe/tests/util/bitbucket_test.rs
@@ -27,70 +27,35 @@ const MESSAGE: &str = "mymessage";
const ORIGIN: &str = "bitbucket.org";
const TOKEN: &str = "bitbuckettoken";
-// Records add/removeConfigSetting calls and serves a configurable getName, mirroring
-// the PHPUnit mock of ConfigSourceInterface used throughout BitbucketTest.
-#[derive(Debug, Clone, Default)]
-struct ConfigSourceCalls {
- added: Vec<(String, PhpMixed)>,
- removed: Vec<String>,
+// Mirrors the PHPUnit mock of ConfigSourceInterface used throughout BitbucketTest.
+// Methods left without an expectation panic if called.
+mockall::mock! {
+ #[derive(Debug)]
+ pub ConfigSource {}
+ impl ConfigSourceInterface for ConfigSource {
+ fn add_repository(&mut self, name: &str, config: PhpMixed, append: bool) -> anyhow::Result<()>;
+ fn insert_repository(&mut self, name: &str, config: PhpMixed, reference_name: &str, offset: i64) -> anyhow::Result<()>;
+ fn set_repository_url(&mut self, name: &str, url: &str) -> anyhow::Result<()>;
+ fn remove_repository(&mut self, name: &str) -> anyhow::Result<()>;
+ fn add_config_setting(&mut self, name: &str, value: PhpMixed) -> anyhow::Result<()>;
+ fn remove_config_setting(&mut self, name: &str) -> anyhow::Result<()>;
+ fn add_property(&mut self, name: &str, value: PhpMixed) -> anyhow::Result<()>;
+ fn remove_property(&mut self, name: &str) -> anyhow::Result<()>;
+ fn add_link(&mut self, r#type: &str, name: &str, value: &str) -> anyhow::Result<()>;
+ fn remove_link(&mut self, r#type: &str, name: &str) -> anyhow::Result<()>;
+ fn get_name(&self) -> String;
+ }
}
-#[derive(Debug)]
-struct ConfigSourceMock {
- name: String,
- calls: Rc<RefCell<ConfigSourceCalls>>,
-}
-
-impl ConfigSourceInterface for ConfigSourceMock {
- fn add_repository(
- &mut self,
- _name: &str,
- _config: PhpMixed,
- _append: bool,
- ) -> anyhow::Result<()> {
- unreachable!()
- }
- fn insert_repository(
- &mut self,
- _name: &str,
- _config: PhpMixed,
- _reference_name: &str,
- _offset: i64,
- ) -> anyhow::Result<()> {
- unreachable!()
- }
- fn set_repository_url(&mut self, _name: &str, _url: &str) -> anyhow::Result<()> {
- unreachable!()
- }
- fn remove_repository(&mut self, _name: &str) -> anyhow::Result<()> {
- unreachable!()
- }
- fn add_config_setting(&mut self, name: &str, value: PhpMixed) -> anyhow::Result<()> {
- self.calls
- .borrow_mut()
- .added
- .push((name.to_string(), value));
- Ok(())
- }
- fn remove_config_setting(&mut self, name: &str) -> anyhow::Result<()> {
- self.calls.borrow_mut().removed.push(name.to_string());
- Ok(())
- }
- fn add_property(&mut self, _name: &str, _value: PhpMixed) -> anyhow::Result<()> {
- unreachable!()
- }
- fn remove_property(&mut self, _name: &str) -> anyhow::Result<()> {
- unreachable!()
- }
- fn add_link(&mut self, _type: &str, _name: &str, _value: &str) -> anyhow::Result<()> {
- unreachable!()
- }
- fn remove_link(&mut self, _type: &str, _name: &str) -> anyhow::Result<()> {
- unreachable!()
- }
- fn get_name(&self) -> String {
- self.name.clone()
- }
+// A bare auth config source placeholder: getAuthConfigSource() is consulted (e.g. while
+// printing instructions), but no add/removeConfigSetting expectations are asserted.
+fn placeholder_auth_config_source() -> Box<MockConfigSource> {
+ let mut mock = MockConfigSource::new();
+ mock.expect_get_name()
+ .returning(|| "auth-config-source".to_string());
+ mock.expect_add_config_setting().returning(|_, _| Ok(()));
+ mock.expect_remove_config_setting().returning(|_| Ok(()));
+ Box::new(mock)
}
// Mirrors BitbucketTest::setUp: a DEBUG-verbosity IOMock, a mocked HttpDownloader, a
@@ -160,34 +125,50 @@ fn access_token_body() -> String {
)
}
-// Installs recording config/auth config sources and returns their shared call logs,
-// mirroring BitbucketTest::setExpectationsForStoringAccessToken.
-struct StoreAccessTokenMocks {
- config_source: Rc<RefCell<ConfigSourceCalls>>,
- auth_config_source: Rc<RefCell<ConfigSourceCalls>>,
-}
-
+// Installs config/auth config source mocks with the access-token storing expectations,
+// mirroring BitbucketTest::setExpectationsForStoringAccessToken. Verification happens
+// when the mocks are dropped together with the Config.
fn set_expectations_for_storing_access_token(
config: &Rc<RefCell<Config>>,
-) -> StoreAccessTokenMocks {
- let config_source = Rc::new(RefCell::new(ConfigSourceCalls::default()));
- let auth_config_source = Rc::new(RefCell::new(ConfigSourceCalls::default()));
+ time: i64,
+ remove_basic_auth: bool,
+) {
+ let mut config_source = MockConfigSource::new();
+ config_source
+ .expect_get_name()
+ .returning(|| "config-source".to_string());
+ let removed_key = format!("bitbucket-oauth.{}", ORIGIN);
+ config_source
+ .expect_remove_config_setting()
+ .times(1)
+ .withf(move |name| name == removed_key)
+ .returning(|_| Ok(()));
config
.borrow_mut()
- .set_config_source(Box::new(ConfigSourceMock {
- name: "config-source".to_string(),
- calls: config_source.clone(),
- }));
+ .set_config_source(Box::new(config_source));
+
+ let mut auth_config_source = MockConfigSource::new();
+ auth_config_source
+ .expect_get_name()
+ .returning(|| "auth-config-source".to_string());
+ let added_key = format!("bitbucket-oauth.{}", ORIGIN);
+ let expected_value = expected_stored_token(time);
+ auth_config_source
+ .expect_add_config_setting()
+ .times(1)
+ .withf(move |name, value| name == added_key && *value == expected_value)
+ .returning(|_, _| Ok(()));
+ if remove_basic_auth {
+ let basic_key = format!("http-basic.{}", ORIGIN);
+ auth_config_source
+ .expect_remove_config_setting()
+ .times(1)
+ .withf(move |name| name == basic_key)
+ .returning(|_| Ok(()));
+ }
config
.borrow_mut()
- .set_auth_config_source(Box::new(ConfigSourceMock {
- name: "auth-config-source".to_string(),
- calls: auth_config_source.clone(),
- }));
- StoreAccessTokenMocks {
- config_source,
- auth_config_source,
- }
+ .set_auth_config_source(Box::new(auth_config_source));
}
fn expected_stored_token(time: i64) -> PhpMixed {
@@ -211,26 +192,6 @@ fn expected_stored_token(time: i64) -> PhpMixed {
PhpMixed::Array(consumer)
}
-fn assert_stored_access_token(mocks: &StoreAccessTokenMocks, time: i64, remove_basic_auth: bool) {
- assert_eq!(
- mocks.config_source.borrow().removed,
- vec![format!("bitbucket-oauth.{}", ORIGIN)],
- );
- assert_eq!(
- mocks.auth_config_source.borrow().added,
- vec![(
- format!("bitbucket-oauth.{}", ORIGIN),
- expected_stored_token(time)
- )],
- );
- if remove_basic_auth {
- assert_eq!(
- mocks.auth_config_source.borrow().removed,
- vec![format!("http-basic.{}", ORIGIN)],
- );
- }
-}
-
#[test]
fn test_request_access_token_with_valid_oauth_consumer() {
let config = ConfigStubBuilder::new().build_shared();
@@ -256,7 +217,7 @@ fn test_request_access_token_with_valid_oauth_consumer() {
)
.unwrap();
- let mocks = set_expectations_for_storing_access_token(&f.config);
+ set_expectations_for_storing_access_token(&f.config, f.time, false);
assert_eq!(
f.bitbucket
@@ -264,8 +225,6 @@ fn test_request_access_token_with_valid_oauth_consumer() {
.unwrap(),
TOKEN
);
-
- assert_stored_access_token(&mocks, f.time, false);
}
#[test]
@@ -357,7 +316,7 @@ fn test_request_access_token_with_valid_oauth_consumer_and_expired_access_token(
)
.unwrap();
- let mocks = set_expectations_for_storing_access_token(&f.config);
+ set_expectations_for_storing_access_token(&f.config, f.time, false);
assert_eq!(
f.bitbucket
@@ -365,8 +324,6 @@ fn test_request_access_token_with_valid_oauth_consumer_and_expired_access_token(
.unwrap(),
TOKEN
);
-
- assert_stored_access_token(&mocks, f.time, false);
}
#[test]
@@ -505,15 +462,13 @@ fn test_username_password_authentication_flow() {
)
.unwrap();
- let mocks = set_expectations_for_storing_access_token(&f.config);
+ set_expectations_for_storing_access_token(&f.config, f.time, true);
assert!(
f.bitbucket
.authorize_oauth_interactively(ORIGIN, Some(MESSAGE))
.unwrap()
);
-
- assert_stored_access_token(&mocks, f.time, true);
}
#[test]
@@ -522,13 +477,9 @@ fn test_authorize_oauth_interactively_with_empty_username() {
let mut f = set_up_with_config_and_http(config, vec![]);
// getAuthConfigSource() is consulted while printing the instructions.
- let auth_calls = Rc::new(RefCell::new(ConfigSourceCalls::default()));
f.config
.borrow_mut()
- .set_auth_config_source(Box::new(ConfigSourceMock {
- name: "auth-config-source".to_string(),
- calls: auth_calls,
- }));
+ .set_auth_config_source(placeholder_auth_config_source());
f.io.borrow_mut()
.expects(vec![Expectation::ask("Consumer Key (hidden): ", "")], false)
@@ -546,13 +497,9 @@ fn test_authorize_oauth_interactively_with_empty_password() {
let config = ConfigStubBuilder::new().build_shared();
let mut f = set_up_with_config_and_http(config, vec![]);
- let auth_calls = Rc::new(RefCell::new(ConfigSourceCalls::default()));
f.config
.borrow_mut()
- .set_auth_config_source(Box::new(ConfigSourceMock {
- name: "auth-config-source".to_string(),
- calls: auth_calls,
- }));
+ .set_auth_config_source(placeholder_auth_config_source());
f.io.borrow_mut()
.expects(
@@ -579,13 +526,9 @@ fn test_authorize_oauth_interactively_with_request_access_token_failure() {
// A 400 status makes the mocked HttpDownloader raise a TransportException(400).
let mut f = set_up_with_config_and_http(config, vec![expect_full(url, None, 400, "", vec![])]);
- let auth_calls = Rc::new(RefCell::new(ConfigSourceCalls::default()));
f.config
.borrow_mut()
- .set_auth_config_source(Box::new(ConfigSourceMock {
- name: "auth-config-source".to_string(),
- calls: auth_calls,
- }));
+ .set_auth_config_source(placeholder_auth_config_source());
f.io.borrow_mut()
.expects(
diff --git a/crates/shirabe/tests/util/forgejo_test.rs b/crates/shirabe/tests/util/forgejo_test.rs
index fd6dbc9..a1a8f9c 100644
--- a/crates/shirabe/tests/util/forgejo_test.rs
+++ b/crates/shirabe/tests/util/forgejo_test.rs
@@ -19,74 +19,49 @@ const ACCESS_TOKEN: &str = "access-token";
const MESSAGE: &str = "mymessage";
const ORIGIN: &str = "codeberg.org";
-// Records the config setting names a source has had removed, plus a fixed getName,
-// mirroring ForgejoTest's JsonConfigSource mocks (getName -> "auth.json", and the
-// config source stubbing removeConfigSetting('forgejo-token.<origin>')).
-#[derive(Debug)]
-struct ConfigSourceMock {
- name: String,
- removed: Rc<RefCell<Vec<String>>>,
+// Mirrors ForgejoTest's JsonConfigSource mocks. Methods left without an expectation
+// panic if called.
+mockall::mock! {
+ #[derive(Debug)]
+ pub ConfigSource {}
+ impl ConfigSourceInterface for ConfigSource {
+ fn add_repository(&mut self, name: &str, config: PhpMixed, append: bool) -> anyhow::Result<()>;
+ fn insert_repository(&mut self, name: &str, config: PhpMixed, reference_name: &str, offset: i64) -> anyhow::Result<()>;
+ fn set_repository_url(&mut self, name: &str, url: &str) -> anyhow::Result<()>;
+ fn remove_repository(&mut self, name: &str) -> anyhow::Result<()>;
+ fn add_config_setting(&mut self, name: &str, value: PhpMixed) -> anyhow::Result<()>;
+ fn remove_config_setting(&mut self, name: &str) -> anyhow::Result<()>;
+ fn add_property(&mut self, name: &str, value: PhpMixed) -> anyhow::Result<()>;
+ fn remove_property(&mut self, name: &str) -> anyhow::Result<()>;
+ fn add_link(&mut self, r#type: &str, name: &str, value: &str) -> anyhow::Result<()>;
+ fn remove_link(&mut self, r#type: &str, name: &str) -> anyhow::Result<()>;
+ fn get_name(&self) -> String;
+ }
}
-impl ConfigSourceMock {
- fn new(name: &str) -> (Box<Self>, Rc<RefCell<Vec<String>>>) {
- let removed = Rc::new(RefCell::new(Vec::new()));
- (
- Box::new(Self {
- name: name.to_string(),
- removed: removed.clone(),
- }),
- removed,
- )
- }
+// getAuthJsonMock: getName atLeastOnce -> "auth.json".
+fn get_auth_json_mock() -> Box<MockConfigSource> {
+ let mut mock = MockConfigSource::new();
+ mock.expect_get_name()
+ .times(1..)
+ .returning(|| "auth.json".to_string());
+ mock.expect_add_config_setting().returning(|_, _| Ok(()));
+ mock.expect_remove_config_setting().returning(|_| Ok(()));
+ Box::new(mock)
}
-impl ConfigSourceInterface for ConfigSourceMock {
- fn add_repository(
- &mut self,
- _name: &str,
- _config: PhpMixed,
- _append: bool,
- ) -> anyhow::Result<()> {
- unreachable!()
- }
- fn insert_repository(
- &mut self,
- _name: &str,
- _config: PhpMixed,
- _reference_name: &str,
- _offset: i64,
- ) -> anyhow::Result<()> {
- unreachable!()
- }
- fn set_repository_url(&mut self, _name: &str, _url: &str) -> anyhow::Result<()> {
- unreachable!()
- }
- fn remove_repository(&mut self, _name: &str) -> anyhow::Result<()> {
- unreachable!()
- }
- fn add_config_setting(&mut self, _name: &str, _value: PhpMixed) -> anyhow::Result<()> {
- Ok(())
- }
- fn remove_config_setting(&mut self, name: &str) -> anyhow::Result<()> {
- self.removed.borrow_mut().push(name.to_string());
- Ok(())
- }
- fn add_property(&mut self, _name: &str, _value: PhpMixed) -> anyhow::Result<()> {
- unreachable!()
- }
- fn remove_property(&mut self, _name: &str) -> anyhow::Result<()> {
- unreachable!()
- }
- fn add_link(&mut self, _type: &str, _name: &str, _value: &str) -> anyhow::Result<()> {
- unreachable!()
- }
- fn remove_link(&mut self, _type: &str, _name: &str) -> anyhow::Result<()> {
- unreachable!()
- }
- fn get_name(&self) -> String {
- self.name.clone()
- }
+// getConfJsonMock: removeConfigSetting atLeastOnce with('forgejo-token.<origin>').
+fn get_conf_json_mock(origin: &str) -> Box<MockConfigSource> {
+ let mut mock = MockConfigSource::new();
+ let expected = format!("forgejo-token.{}", origin);
+ mock.expect_remove_config_setting()
+ .times(1..)
+ .withf(move |name| name == expected)
+ .returning(|_| Ok(()));
+ mock.expect_add_config_setting().returning(|_, _| Ok(()));
+ mock.expect_get_name()
+ .returning(|| "config.json".to_string());
+ Box::new(mock)
}
fn build_forgejo(
@@ -126,10 +101,12 @@ fn test_username_password_authentication_flow() {
);
let config = ConfigStubBuilder::new().build_shared();
- let (auth_source, _) = ConfigSourceMock::new("auth.json");
- let (conf_source, conf_removed) = ConfigSourceMock::new("config.json");
- config.borrow_mut().set_auth_config_source(auth_source);
- config.borrow_mut().set_config_source(conf_source);
+ config
+ .borrow_mut()
+ .set_auth_config_source(get_auth_json_mock());
+ config
+ .borrow_mut()
+ .set_config_source(get_conf_json_mock(ORIGIN));
let mut forgejo = build_forgejo(&io_mock, config, http_downloader);
@@ -139,10 +116,7 @@ fn test_username_password_authentication_flow() {
.unwrap()
.unwrap()
);
- assert_eq!(
- *conf_removed.borrow(),
- vec![format!("forgejo-token.{}", ORIGIN)]
- );
+ // removeConfigSetting('forgejo-token.<origin>') verified on the conf source mock drop.
}
#[test]
@@ -172,8 +146,9 @@ fn test_username_password_failure() {
);
let config = ConfigStubBuilder::new().build_shared();
- let (auth_source, _) = ConfigSourceMock::new("auth.json");
- config.borrow_mut().set_auth_config_source(auth_source);
+ config
+ .borrow_mut()
+ .set_auth_config_source(get_auth_json_mock());
let mut forgejo = build_forgejo(&io_mock, config, http_downloader);
diff --git a/crates/shirabe/tests/util/github_test.rs b/crates/shirabe/tests/util/github_test.rs
index 10b5dd7..0069a9c 100644
--- a/crates/shirabe/tests/util/github_test.rs
+++ b/crates/shirabe/tests/util/github_test.rs
@@ -18,74 +18,49 @@ const PASSWORD: &str = "password";
const MESSAGE: &str = "mymessage";
const ORIGIN: &str = "github.com";
-// Records the config setting names a source has had removed, plus a fixed getName,
-// mirroring GitHubTest's JsonConfigSource mocks (getName -> "auth.json", and the
-// config source stubbing removeConfigSetting('github-oauth.<origin>')).
-#[derive(Debug)]
-struct ConfigSourceMock {
- name: String,
- removed: Rc<RefCell<Vec<String>>>,
+// Mirrors GitHubTest's JsonConfigSource mocks. Methods left without an expectation
+// panic if called.
+mockall::mock! {
+ #[derive(Debug)]
+ pub ConfigSource {}
+ impl ConfigSourceInterface for ConfigSource {
+ fn add_repository(&mut self, name: &str, config: PhpMixed, append: bool) -> anyhow::Result<()>;
+ fn insert_repository(&mut self, name: &str, config: PhpMixed, reference_name: &str, offset: i64) -> anyhow::Result<()>;
+ fn set_repository_url(&mut self, name: &str, url: &str) -> anyhow::Result<()>;
+ fn remove_repository(&mut self, name: &str) -> anyhow::Result<()>;
+ fn add_config_setting(&mut self, name: &str, value: PhpMixed) -> anyhow::Result<()>;
+ fn remove_config_setting(&mut self, name: &str) -> anyhow::Result<()>;
+ fn add_property(&mut self, name: &str, value: PhpMixed) -> anyhow::Result<()>;
+ fn remove_property(&mut self, name: &str) -> anyhow::Result<()>;
+ fn add_link(&mut self, r#type: &str, name: &str, value: &str) -> anyhow::Result<()>;
+ fn remove_link(&mut self, r#type: &str, name: &str) -> anyhow::Result<()>;
+ fn get_name(&self) -> String;
+ }
}
-impl ConfigSourceMock {
- fn new(name: &str) -> (Box<Self>, Rc<RefCell<Vec<String>>>) {
- let removed = Rc::new(RefCell::new(Vec::new()));
- (
- Box::new(Self {
- name: name.to_string(),
- removed: removed.clone(),
- }),
- removed,
- )
- }
+// getAuthJsonMock: getName atLeastOnce -> "auth.json".
+fn get_auth_json_mock() -> Box<MockConfigSource> {
+ let mut mock = MockConfigSource::new();
+ mock.expect_get_name()
+ .times(1..)
+ .returning(|| "auth.json".to_string());
+ mock.expect_add_config_setting().returning(|_, _| Ok(()));
+ mock.expect_remove_config_setting().returning(|_| Ok(()));
+ Box::new(mock)
}
-impl ConfigSourceInterface for ConfigSourceMock {
- fn add_repository(
- &mut self,
- _name: &str,
- _config: PhpMixed,
- _append: bool,
- ) -> anyhow::Result<()> {
- unreachable!()
- }
- fn insert_repository(
- &mut self,
- _name: &str,
- _config: PhpMixed,
- _reference_name: &str,
- _offset: i64,
- ) -> anyhow::Result<()> {
- unreachable!()
- }
- fn set_repository_url(&mut self, _name: &str, _url: &str) -> anyhow::Result<()> {
- unreachable!()
- }
- fn remove_repository(&mut self, _name: &str) -> anyhow::Result<()> {
- unreachable!()
- }
- fn add_config_setting(&mut self, _name: &str, _value: PhpMixed) -> anyhow::Result<()> {
- Ok(())
- }
- fn remove_config_setting(&mut self, name: &str) -> anyhow::Result<()> {
- self.removed.borrow_mut().push(name.to_string());
- Ok(())
- }
- fn add_property(&mut self, _name: &str, _value: PhpMixed) -> anyhow::Result<()> {
- unreachable!()
- }
- fn remove_property(&mut self, _name: &str) -> anyhow::Result<()> {
- unreachable!()
- }
- fn add_link(&mut self, _type: &str, _name: &str, _value: &str) -> anyhow::Result<()> {
- unreachable!()
- }
- fn remove_link(&mut self, _type: &str, _name: &str) -> anyhow::Result<()> {
- unreachable!()
- }
- fn get_name(&self) -> String {
- self.name.clone()
- }
+// getConfJsonMock: removeConfigSetting atLeastOnce with('github-oauth.<origin>').
+fn get_conf_json_mock(origin: &str) -> Box<MockConfigSource> {
+ let mut mock = MockConfigSource::new();
+ let expected = format!("github-oauth.{}", origin);
+ mock.expect_remove_config_setting()
+ .times(1..)
+ .withf(move |name| name == expected)
+ .returning(|_| Ok(()));
+ mock.expect_add_config_setting().returning(|_, _| Ok(()));
+ mock.expect_get_name()
+ .returning(|| "config.json".to_string());
+ Box::new(mock)
}
fn build_github(
@@ -133,10 +108,12 @@ fn test_username_password_authentication_flow() {
);
let config = build_config();
- let (auth_source, _) = ConfigSourceMock::new("auth.json");
- let (conf_source, conf_removed) = ConfigSourceMock::new("config.json");
- config.borrow_mut().set_auth_config_source(auth_source);
- config.borrow_mut().set_config_source(conf_source);
+ config
+ .borrow_mut()
+ .set_auth_config_source(get_auth_json_mock());
+ config
+ .borrow_mut()
+ .set_config_source(get_conf_json_mock(ORIGIN));
let mut github = build_github(&io_mock, config, http_downloader);
@@ -145,10 +122,7 @@ fn test_username_password_authentication_flow() {
.authorize_oauth_interactively(ORIGIN, Some(MESSAGE))
.unwrap()
);
- assert_eq!(
- *conf_removed.borrow(),
- vec![format!("github-oauth.{}", ORIGIN)]
- );
+ // removeConfigSetting('github-oauth.<origin>') verified on the conf source mock drop.
}
#[test]
@@ -172,8 +146,9 @@ fn test_username_password_failure() {
);
let config = build_config();
- let (auth_source, _) = ConfigSourceMock::new("auth.json");
- config.borrow_mut().set_auth_config_source(auth_source);
+ config
+ .borrow_mut()
+ .set_auth_config_source(get_auth_json_mock());
let mut github = build_github(&io_mock, config, http_downloader);
diff --git a/crates/shirabe/tests/util/gitlab_test.rs b/crates/shirabe/tests/util/gitlab_test.rs
index ebf7c08..a3db85b 100644
--- a/crates/shirabe/tests/util/gitlab_test.rs
+++ b/crates/shirabe/tests/util/gitlab_test.rs
@@ -22,61 +22,40 @@ const TOKEN: &str = "gitlabtoken";
const REFRESHTOKEN: &str = "gitlabrefreshtoken";
// Mirrors GitLabTest::getAuthJsonMock: a JsonConfigSource whose getName() returns
-// "auth.json" and whose addConfigSetting is a no-op (the PHP mock never stubs it).
-#[derive(Debug)]
-struct AuthJsonMock;
-
-impl ConfigSourceInterface for AuthJsonMock {
- fn add_repository(
- &mut self,
- _name: &str,
- _config: PhpMixed,
- _append: bool,
- ) -> anyhow::Result<()> {
- unreachable!()
- }
- fn insert_repository(
- &mut self,
- _name: &str,
- _config: PhpMixed,
- _reference_name: &str,
- _offset: i64,
- ) -> anyhow::Result<()> {
- unreachable!()
- }
- fn set_repository_url(&mut self, _name: &str, _url: &str) -> anyhow::Result<()> {
- unreachable!()
- }
- fn remove_repository(&mut self, _name: &str) -> anyhow::Result<()> {
- unreachable!()
- }
- 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<()> {
- unreachable!()
- }
- fn remove_property(&mut self, _name: &str) -> anyhow::Result<()> {
- unreachable!()
- }
- fn add_link(&mut self, _type: &str, _name: &str, _value: &str) -> anyhow::Result<()> {
- unreachable!()
- }
- fn remove_link(&mut self, _type: &str, _name: &str) -> anyhow::Result<()> {
- unreachable!()
- }
- fn get_name(&self) -> String {
- "auth.json".to_string()
+// "auth.json" (atLeastOnce) and whose addConfigSetting is a no-op (the PHP mock
+// never stubs it). Methods left without an expectation panic if called.
+mockall::mock! {
+ #[derive(Debug)]
+ pub AuthJson {}
+ impl ConfigSourceInterface for AuthJson {
+ fn add_repository(&mut self, name: &str, config: PhpMixed, append: bool) -> anyhow::Result<()>;
+ fn insert_repository(&mut self, name: &str, config: PhpMixed, reference_name: &str, offset: i64) -> anyhow::Result<()>;
+ fn set_repository_url(&mut self, name: &str, url: &str) -> anyhow::Result<()>;
+ fn remove_repository(&mut self, name: &str) -> anyhow::Result<()>;
+ fn add_config_setting(&mut self, name: &str, value: PhpMixed) -> anyhow::Result<()>;
+ fn remove_config_setting(&mut self, name: &str) -> anyhow::Result<()>;
+ fn add_property(&mut self, name: &str, value: PhpMixed) -> anyhow::Result<()>;
+ fn remove_property(&mut self, name: &str) -> anyhow::Result<()>;
+ fn add_link(&mut self, r#type: &str, name: &str, value: &str) -> anyhow::Result<()>;
+ fn remove_link(&mut self, r#type: &str, name: &str) -> anyhow::Result<()>;
+ fn get_name(&self) -> String;
}
}
+fn get_auth_json_mock() -> Box<MockAuthJson> {
+ let mut mock = MockAuthJson::new();
+ mock.expect_get_name()
+ .times(1..)
+ .returning(|| "auth.json".to_string());
+ mock.expect_add_config_setting().returning(|_, _| Ok(()));
+ mock.expect_remove_config_setting().returning(|_| Ok(()));
+ Box::new(mock)
+}
+
fn set_up(io_mock: &Rc<RefCell<IOMock>>, config: &Rc<RefCell<Config>>) {
config
.borrow_mut()
- .set_auth_config_source(Box::new(AuthJsonMock));
+ .set_auth_config_source(get_auth_json_mock());
let _ = io_mock;
}