chore(deps): update rust crate kxio to v5
All checks were successful
Test / build (map[name:stable]) (push) Successful in 11m21s
Test / build (map[name:nightly]) (push) Successful in 12m40s
Release Please / Release-plz (push) Successful in 1m8s
Release Please / Docker image (push) Successful in 10m26s

This commit is contained in:
Renovate Bot 2025-01-16 16:42:44 +00:00 committed by Paul Campbell
parent f8625a59f8
commit a8298d943a
10 changed files with 267 additions and 140 deletions

40
Cargo.lock generated
View file

@ -1098,7 +1098,7 @@ dependencies = [
"rand",
"ratatui",
"regex",
"rstest",
"rstest 0.24.0",
"secrecy",
"sendmail",
"serde_json",
@ -2747,9 +2747,9 @@ dependencies = [
[[package]]
name = "kxio"
version = "4.0.0"
version = "5.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b711909378294af8b006b4df66e8b2de75fc0c2c98ff9ea7ef1422ae7c859a3d"
checksum = "ec15c915b6fb790d4dac6c1c101c01d29bd4701e5d55e48ae47bad69356eb7b4"
dependencies = [
"base64 0.22.1",
"bytes",
@ -3692,7 +3692,19 @@ checksum = "0a2c585be59b6b5dd66a9d2084aa1d8bd52fbdb806eafdeffb52791147862035"
dependencies = [
"futures",
"futures-timer",
"rstest_macros",
"rstest_macros 0.23.0",
"rustc_version",
]
[[package]]
name = "rstest"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03e905296805ab93e13c1ec3a03f4b6c4f35e9498a3d5fa96dc626d22c03cd89"
dependencies = [
"futures-timer",
"futures-util",
"rstest_macros 0.24.0",
"rustc_version",
]
@ -3714,6 +3726,24 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "rstest_macros"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef0053bbffce09062bee4bcc499b0fbe7a57b879f1efe088d6d8d4c7adcdef9b"
dependencies = [
"cfg-if",
"glob",
"proc-macro-crate",
"proc-macro2",
"quote",
"regex",
"relative-path",
"rustc_version",
"syn",
"unicode-ident",
]
[[package]]
name = "rust-argon2"
version = "0.8.3"
@ -4530,7 +4560,7 @@ checksum = "235ee99b9af57bc0bc8cf42604f5868641690ed652001120d63ca2784a41c3d3"
dependencies = [
"indoc",
"ratatui",
"rstest",
"rstest 0.23.0",
]
[[package]]

View file

@ -60,7 +60,7 @@ async-trait = "0.1"
git-url-parse = "0.4"
# fs/network
kxio = "4.0"
kxio = "5.0"
native-tls = { version = "0.2", features = ["vendored"] }

View file

@ -11,19 +11,21 @@ use git_next_core::{
#[cfg(feature = "forgejo")]
#[test]
fn test_forgejo_name() {
let net = kxio::net::mock();
let mock_net = kxio::net::mock();
let repo_details = given_repo_details(git_next_core::ForgeType::ForgeJo);
let forge = Forge::create(repo_details, net.into());
let forge = Forge::create(repo_details, mock_net.clone().into());
assert_eq!(forge.name(), "forgejo");
mock_net.assert_no_unused_plans();
}
#[cfg(feature = "github")]
#[test]
fn test_github_name() {
let net = kxio::net::mock();
let mock_net = kxio::net::mock();
let repo_details = given_repo_details(git_next_core::ForgeType::GitHub);
let forge = Forge::create(repo_details, net.into());
let forge = Forge::create(repo_details, mock_net.clone().into());
assert_eq!(forge.name(), "github");
mock_net.assert_no_unused_plans();
}
#[allow(dead_code)]

View file

@ -35,7 +35,7 @@ async fn should_clone() -> TestResult {
repo_details,
given::a_forge(),
fs.as_real(),
net,
net.clone(),
);
tell!(addr, CloneRepo::new())?;
//then
@ -44,6 +44,7 @@ async fn should_clone() -> TestResult {
.read()
.map_err(|e| e.to_string())
.map(|o| assert_eq!(o.len(), 1))?;
net.assert_no_unused_plans();
Ok(())
}
@ -78,7 +79,7 @@ async fn should_open() -> TestResult {
repo_details,
given::a_forge(),
fs.as_real(),
net,
net.clone(),
);
tell!(addr, CloneRepo::new())?;
@ -88,6 +89,7 @@ async fn should_open() -> TestResult {
.read()
.map_err(|e| e.to_string())
.map(|o| assert_eq!(o.len(), 1))?;
net.assert_no_unused_plans();
Ok(())
}
@ -120,13 +122,14 @@ async fn when_server_has_no_repo_config_should_send_load_from_repo() -> TestResu
repo_details,
given::a_forge(),
fs.as_real(),
net,
net.clone(),
);
tell!(addr, CloneRepo::new())?;
//then
log.require_message_containing("send: LoadConfigFromRepo")
.await?;
net.assert_no_unused_plans();
Ok(())
}
@ -156,7 +159,7 @@ async fn when_server_has_repo_config_should_send_register_webhook() -> TestResul
repo_details,
given::a_forge(),
fs.as_real(),
net,
net.clone(),
);
tell!(addr, CloneRepo::new())?;
@ -165,6 +168,7 @@ async fn when_server_has_repo_config_should_send_register_webhook() -> TestResul
debug!(?log, "");
log.require_message_containing("send: RegisterWebhook")
.await?;
net.assert_no_unused_plans();
Ok(())
}

View file

@ -396,7 +396,7 @@ async fn should_accept_message_with_current_token() -> TestResult {
git::repository::factory::mock(),
given::a_forge(),
server_actor_ref,
net,
net.clone(),
);
let actor = actor.with_message_token(MessageToken::new(2_u32));
let addr = kameo::spawn(actor);
@ -406,6 +406,7 @@ async fn should_accept_message_with_current_token() -> TestResult {
//then
log.require_message_containing("accepted token: 2").await?;
net.assert_no_unused_plans();
Ok(())
}
@ -422,7 +423,7 @@ async fn should_accept_message_with_new_token() -> TestResult {
git::repository::factory::mock(),
given::a_forge(),
given::a_server_actor(fs.as_real(), net.clone()),
net,
net.clone(),
);
let actor = actor.with_message_token(MessageToken::new(2_u32));
let addr = kameo::spawn(actor);
@ -430,6 +431,7 @@ async fn should_accept_message_with_new_token() -> TestResult {
//then
log.require_message_containing("accepted token: 3").await?;
net.assert_no_unused_plans();
Ok(())
}
@ -446,7 +448,7 @@ async fn should_reject_message_with_expired_token() -> TestResult {
git::repository::factory::mock(),
given::a_forge(),
given::a_server_actor(fs.as_real(), net.clone()),
net,
net.clone(),
);
let actor = actor.with_message_token(MessageToken::new(4_u32));
let addr = kameo::spawn(actor);
@ -454,6 +456,7 @@ async fn should_reject_message_with_expired_token() -> TestResult {
//then
log.no_message_contains("accepted token").await?;
net.assert_no_unused_plans();
Ok(())
}

View file

@ -22,7 +22,7 @@ async fn when_no_expected_auth_token_drop_notification() -> TestResult {
Box::new(repository_factory),
given::a_forge(),
given::a_server_actor(fs.as_real(), net.clone()),
net,
net.clone(),
);
let actor = actor.with_webhook_auth(None);
@ -36,6 +36,7 @@ async fn when_no_expected_auth_token_drop_notification() -> TestResult {
log.no_message_contains("send").await?;
log.require_message_containing("server has no auth token")
.await?;
net.assert_no_unused_plans();
Ok(())
}
@ -56,7 +57,7 @@ async fn when_no_repo_config_drop_notification() -> TestResult {
Box::new(repository_factory),
given::a_forge(),
given::a_server_actor(fs.as_real(), net.clone()),
net,
net.clone(),
);
let actor = actor.with_webhook_auth(Some(given::a_webhook_auth()));
@ -70,6 +71,7 @@ async fn when_no_repo_config_drop_notification() -> TestResult {
log.no_message_contains("send").await?;
log.require_message_containing("server has no repo config")
.await?;
net.assert_no_unused_plans();
Ok(())
}
@ -94,7 +96,7 @@ async fn when_message_auth_is_invalid_drop_notification() -> TestResult {
Box::new(repository_factory),
forge,
given::a_server_actor(fs.as_real(), net.clone()),
net,
net.clone(),
);
let actor = actor.with_webhook_auth(Some(given::a_webhook_auth()));
@ -108,6 +110,7 @@ async fn when_message_auth_is_invalid_drop_notification() -> TestResult {
log.no_message_contains("send").await?;
log.require_message_containing("message authorisation is invalid")
.await?;
net.assert_no_unused_plans();
Ok(())
}
@ -136,7 +139,7 @@ async fn when_message_is_ignorable_drop_notification() -> TestResult {
Box::new(repository_factory),
forge,
given::a_server_actor(fs.as_real(), net.clone()),
net,
net.clone(),
);
let actor = actor.with_webhook_auth(Some(given::a_webhook_auth()));
@ -150,6 +153,7 @@ async fn when_message_is_ignorable_drop_notification() -> TestResult {
log.no_message_contains("send").await?;
log.require_message_containing("forge sent ignorable message")
.await?;
net.assert_no_unused_plans();
Ok(())
}
@ -178,7 +182,7 @@ async fn when_message_is_not_a_push_drop_notification() -> TestResult {
Box::new(repository_factory),
forge,
given::a_server_actor(fs.as_real(), net.clone()),
net,
net.clone(),
);
let actor = actor.with_webhook_auth(Some(given::a_webhook_auth()));
@ -192,6 +196,7 @@ async fn when_message_is_not_a_push_drop_notification() -> TestResult {
log.no_message_contains("send").await?;
log.require_message_containing("message parse error - not a push")
.await?;
net.assert_no_unused_plans();
Ok(())
}
@ -224,7 +229,7 @@ async fn when_message_is_push_on_unknown_branch_drop_notification() -> TestResul
Box::new(repository_factory),
forge,
given::a_server_actor(fs.as_real(), net.clone()),
net,
net.clone(),
);
let actor = actor
.with_webhook_auth(Some(given::a_webhook_auth()))
@ -239,6 +244,7 @@ async fn when_message_is_push_on_unknown_branch_drop_notification() -> TestResul
//then
log.no_message_contains("send").await?;
log.require_message_containing("unknown branch").await?;
net.assert_no_unused_plans();
Ok(())
}
@ -272,7 +278,7 @@ async fn when_message_is_push_already_seen_commit_to_main() -> TestResult {
Box::new(repository_factory),
forge,
given::a_server_actor(fs.as_real(), net.clone()),
net,
net.clone(),
);
let actor = actor
.with_webhook_auth(Some(given::a_webhook_auth()))
@ -288,6 +294,7 @@ async fn when_message_is_push_already_seen_commit_to_main() -> TestResult {
log.no_message_contains("send").await?;
log.require_message_containing(format!("not a new commit on {main}"))
.await?;
net.assert_no_unused_plans();
Ok(())
}
@ -321,7 +328,7 @@ async fn when_message_is_push_already_seen_commit_to_next() -> TestResult {
Box::new(repository_factory),
forge,
given::a_server_actor(fs.as_real(), net.clone()),
net,
net.clone(),
);
let actor = actor
.with_webhook_auth(Some(given::a_webhook_auth()))
@ -337,6 +344,7 @@ async fn when_message_is_push_already_seen_commit_to_next() -> TestResult {
log.no_message_contains("send").await?;
log.require_message_containing(format!("not a new commit on {next_branch}"))
.await?;
net.assert_no_unused_plans();
Ok(())
}
@ -370,7 +378,7 @@ async fn when_message_is_push_already_seen_commit_to_dev() -> TestResult {
Box::new(repository_factory),
forge,
given::a_server_actor(fs.as_real(), net.clone()),
net,
net.clone(),
);
let actor = actor
.with_webhook_auth(Some(given::a_webhook_auth()))
@ -386,6 +394,7 @@ async fn when_message_is_push_already_seen_commit_to_dev() -> TestResult {
log.no_message_contains("send").await?;
log.require_message_containing(format!("not a new commit on {dev}"))
.await?;
net.assert_no_unused_plans();
Ok(())
}
@ -418,7 +427,7 @@ async fn when_message_is_push_new_commit_to_main_should_stash_and_validate_repo(
Box::new(repository_factory),
forge,
given::a_server_actor(fs.as_real(), net.clone()),
net,
net.clone(),
);
let actor = actor
.with_webhook_auth(Some(given::a_webhook_auth()))
@ -435,6 +444,7 @@ async fn when_message_is_push_new_commit_to_main_should_stash_and_validate_repo(
.map_err(|e| format!("examine actor: {e:?}"))?;
assert_eq!(view.last_main_commit, Some(push_commit));
log.require_message_containing("send: ValidateRepo").await?;
net.assert_no_unused_plans();
Ok(())
}
@ -467,7 +477,7 @@ async fn when_message_is_push_new_commit_to_next_should_stash_and_validate_repo(
Box::new(repository_factory),
forge,
given::a_server_actor(fs.as_real(), net.clone()),
net,
net.clone(),
);
let actor = actor
.with_webhook_auth(Some(given::a_webhook_auth()))
@ -484,6 +494,7 @@ async fn when_message_is_push_new_commit_to_next_should_stash_and_validate_repo(
.map_err(|e| format!("examine actor: {e:?}"))?;
assert_eq!(view.last_next_commit, Some(push_commit));
log.require_message_containing("send: ValidateRepo").await?;
net.assert_no_unused_plans();
Ok(())
}
@ -516,7 +527,7 @@ async fn when_message_is_push_new_commit_to_dev_should_stash_and_validate_repo()
Box::new(repository_factory),
forge,
given::a_server_actor(fs.as_real(), net.clone()),
net,
net.clone(),
);
let actor = actor
.with_webhook_auth(Some(given::a_webhook_auth()))
@ -533,5 +544,6 @@ async fn when_message_is_push_new_commit_to_dev_should_stash_and_validate_repo()
.map_err(|e| format!("examine actor: {e:?}"))?;
assert_eq!(view.last_dev_commit, Some(push_commit));
log.require_message_containing("send: ValidateRepo").await?;
net.assert_no_unused_plans();
Ok(())
}

View file

@ -23,8 +23,8 @@ async fn when_webhook_url_has_trailing_slash_should_not_send() -> TestResult {
//given
// parameters
let fs = given::a_filesystem();
let net = given::a_network();
let alerts = given::an_alerts_actor(net.clone().into());
let mock_net = given::a_network();
let alerts = given::an_alerts_actor(mock_net.clone().into());
let repo = git::repository::factory::mock();
let duration = std::time::Duration::from_millis(1);
@ -34,7 +34,7 @@ async fn when_webhook_url_has_trailing_slash_should_not_send() -> TestResult {
let server = ServerActor::new(
false, // ui
fs.as_real(),
net.into(),
mock_net.clone().into(),
alerts,
file_update_subs,
repo,
@ -67,6 +67,7 @@ async fn when_webhook_url_has_trailing_slash_should_not_send() -> TestResult {
assert!(message_log.read().iter().any(|log| !log
.iter()
.any(|line| line == "send: ReceiveValidServerConfig")));
mock_net.assert_no_unused_plans();
Ok(())
}

View file

@ -23,8 +23,10 @@ mod forgejo {
#[test]
fn should_return_name() {
let fs = given::a_filesystem();
let forge = given::a_forgejo_forge(&given::repo_details(&fs), given::a_network());
let mock_net = given::a_network();
let forge = given::a_forgejo_forge(&given::repo_details(&fs), mock_net.clone());
assert_eq!(forge.name(), "forgejo");
mock_net.assert_no_unused_plans();
}
mod is_message_authorised {
@ -34,42 +36,52 @@ mod forgejo {
#[test]
fn should_return_true_with_valid_header() {
let fs = given::a_filesystem();
let forge = given::a_forgejo_forge(&given::repo_details(&fs), given::a_network());
let mock_net = given::a_network();
let forge = given::a_forgejo_forge(&given::repo_details(&fs), mock_net.clone());
let auth = given::a_webhook_auth();
let message = given::a_webhook_message(given::Header::Valid(auth.clone()));
assert!(forge.is_message_authorised(&message, &auth));
mock_net.assert_no_unused_plans();
}
#[test]
fn should_return_false_with_missing_header() {
let fs = given::a_filesystem();
let forge = given::a_forgejo_forge(&given::repo_details(&fs), given::a_network());
let mock_net = given::a_network();
let forge = given::a_forgejo_forge(&given::repo_details(&fs), mock_net.clone());
let auth = given::a_webhook_auth();
let message = given::a_webhook_message(given::Header::Missing);
assert!(!forge.is_message_authorised(&message, &auth));
mock_net.assert_no_unused_plans();
}
#[test]
fn should_return_false_with_non_basic_prefix() {
let fs = given::a_filesystem();
let forge = given::a_forgejo_forge(&given::repo_details(&fs), given::a_network());
let mock_net = given::a_network();
let forge = given::a_forgejo_forge(&given::repo_details(&fs), mock_net.clone());
let auth = given::a_webhook_auth();
let message = given::a_webhook_message(given::Header::NonBasic);
assert!(!forge.is_message_authorised(&message, &auth));
mock_net.assert_no_unused_plans();
}
#[test]
fn should_return_false_with_non_ulid_value() {
let fs = given::a_filesystem();
let forge = given::a_forgejo_forge(&given::repo_details(&fs), given::a_network());
let mock_net = given::a_network();
let forge = given::a_forgejo_forge(&given::repo_details(&fs), mock_net.clone());
let auth = given::a_webhook_auth();
let message = given::a_webhook_message(given::Header::NonUlid);
assert!(!forge.is_message_authorised(&message, &auth));
mock_net.assert_no_unused_plans();
}
#[test]
fn should_return_false_with_wrong_ulid_value() {
let fs = given::a_filesystem();
let forge = given::a_forgejo_forge(&given::repo_details(&fs), given::a_network());
let mock_net = given::a_network();
let forge = given::a_forgejo_forge(&given::repo_details(&fs), mock_net.clone());
let auth = given::a_webhook_auth();
let message = given::a_webhook_message(given::Header::WrongUlid);
assert!(!forge.is_message_authorised(&message, &auth));
mock_net.assert_no_unused_plans();
}
}
@ -80,7 +92,8 @@ mod forgejo {
#[test]
fn should_parse_valid_body() {
let fs = given::a_filesystem();
let forge = given::a_forgejo_forge(&given::repo_details(&fs), given::a_network());
let mock_net = given::a_network();
let forge = given::a_forgejo_forge(&given::repo_details(&fs), mock_net.clone());
let repo_branches = given::repo_branches();
let next = repo_branches.next();
let sha = given::a_name();
@ -96,16 +109,19 @@ mod forgejo {
push.branch(&repo_branches),
Some(git_next_core::webhook::push::Branch::Next)
);
mock_net.assert_no_unused_plans();
}
#[test]
fn should_error_invalid_body() {
let fs = given::a_filesystem();
let forge = given::a_forgejo_forge(&given::repo_details(&fs), given::a_network());
let mock_net = given::a_network();
let forge = given::a_forgejo_forge(&given::repo_details(&fs), mock_net.clone());
let body = git_next_core::webhook::forge_notification::Body::new(
r#"{"type":"invalid"}"#.to_string(),
);
let_assert!(Err(_) = forge.parse_webhook_body(&body));
mock_net.assert_no_unused_plans();
}
}
@ -118,73 +134,79 @@ mod forgejo {
let fs = given::a_filesystem();
let repo_details = given::repo_details(&fs);
let commit = given::a_commit();
let net = given::a_network();
given::a_commit_state("success", &net, &repo_details, &commit);
let forge = given::a_forgejo_forge(&repo_details, net);
let mock_net = given::a_network();
given::a_commit_state("success", &mock_net, &repo_details, &commit);
let forge = given::a_forgejo_forge(&repo_details, mock_net.clone());
assert_eq!(
forge.commit_status(&commit).await.expect("status"),
Status::Pass
);
mock_net.assert_no_unused_plans();
}
#[tokio::test]
async fn should_return_pending_for_pending() {
let fs = given::a_filesystem();
let repo_details = given::repo_details(&fs);
let commit = given::a_commit();
let net = given::a_network();
given::a_commit_state("pending", &net, &repo_details, &commit);
let forge = given::a_forgejo_forge(&repo_details, net);
let mock_net = given::a_network();
given::a_commit_state("pending", &mock_net, &repo_details, &commit);
let forge = given::a_forgejo_forge(&repo_details, mock_net.clone());
assert_eq!(
forge.commit_status(&commit).await.expect("status"),
Status::Pending
);
mock_net.assert_no_unused_plans();
}
#[tokio::test]
async fn should_return_fail_for_failure() {
let fs = given::a_filesystem();
let repo_details = given::repo_details(&fs);
let commit = given::a_commit();
let net = given::a_network();
given::a_commit_state("failure", &net, &repo_details, &commit);
let forge = given::a_forgejo_forge(&repo_details, net);
let mock_net = given::a_network();
given::a_commit_state("failure", &mock_net, &repo_details, &commit);
let forge = given::a_forgejo_forge(&repo_details, mock_net.clone());
assert_eq!(
forge.commit_status(&commit).await.expect("status"),
Status::Fail
);
mock_net.assert_no_unused_plans();
}
#[tokio::test]
async fn should_return_fail_for_error() {
let fs = given::a_filesystem();
let repo_details = given::repo_details(&fs);
let commit = given::a_commit();
let net = given::a_network();
given::a_commit_state("error", &net, &repo_details, &commit);
let forge = given::a_forgejo_forge(&repo_details, net);
let mock_net = given::a_network();
given::a_commit_state("error", &mock_net, &repo_details, &commit);
let forge = given::a_forgejo_forge(&repo_details, mock_net.clone());
assert_eq!(
forge.commit_status(&commit).await.expect("status"),
Status::Fail
);
mock_net.assert_no_unused_plans();
}
#[tokio::test]
async fn should_return_pending_for_blank() {
let fs = given::a_filesystem();
let repo_details = given::repo_details(&fs);
let commit = given::a_commit();
let net = given::a_network();
given::a_commit_state("", &net, &repo_details, &commit);
let forge = given::a_forgejo_forge(&repo_details, net);
let mock_net = given::a_network();
given::a_commit_state("", &mock_net, &repo_details, &commit);
let forge = given::a_forgejo_forge(&repo_details, mock_net.clone());
assert_eq!(
forge.commit_status(&commit).await.expect("status"),
Status::Pending
);
mock_net.assert_no_unused_plans();
}
#[tokio::test]
async fn should_return_pending_for_no_statuses() {
let fs = given::a_filesystem();
let repo_details = given::repo_details(&fs);
let commit = given::a_commit();
let net = given::a_network();
net.on()
let mock_net = given::a_network();
mock_net
.on()
.get(given::a_commit_status_url(&repo_details, &commit))
.respond(StatusCode::OK)
.body(
@ -194,11 +216,12 @@ mod forgejo {
.to_string(),
)
.expect("mock");
let forge = given::a_forgejo_forge(&repo_details, net);
let forge = given::a_forgejo_forge(&repo_details, mock_net.clone());
assert_eq!(
forge.commit_status(&commit).await.expect("status"),
Status::Pending
);
mock_net.assert_no_unused_plans();
}
#[tokio::test]
async fn should_return_pending_for_network_error() {
@ -212,11 +235,12 @@ mod forgejo {
.respond(StatusCode::INTERNAL_SERVER_ERROR)
.body("book today")
.expect("mock");
let forge = given::a_forgejo_forge(&repo_details, mock_net);
let forge = given::a_forgejo_forge(&repo_details, mock_net.clone());
assert_eq!(
forge.commit_status(&commit).await.expect("status"),
Status::Pending
);
mock_net.assert_no_unused_plans();
}
}
@ -235,10 +259,10 @@ mod forgejo {
let hook_id_1 = given::a_forgejo_webhook_id();
let hook_id_2 = given::a_forgejo_webhook_id();
let hook_id_3 = given::a_forgejo_webhook_id();
let mut net = given::a_network();
let mock_net = given::a_network();
let mut args = with::WebhookArgs {
net: &mut net,
mock_net: &mock_net,
hostname,
repo_path,
token,
@ -256,7 +280,7 @@ mod forgejo {
// page 2 with no items - stops pagination
with::get_webhooks_by_page(2, &[], &mut args);
let forge = given::a_forgejo_forge(&repo_details, net);
let forge = given::a_forgejo_forge(&repo_details, mock_net.clone());
let_assert!(Ok(result) = forge.list_webhooks(&repo_listen_url).await);
assert_eq!(
@ -266,6 +290,7 @@ mod forgejo {
WebhookId::new(format!("{hook_id_2}"))
]
);
mock_net.assert_no_unused_plans();
}
#[tokio::test]
@ -276,9 +301,10 @@ mod forgejo {
let hostname = repo_details.forge.hostname();
let repo_path = &repo_details.repo_path;
let token = repo_details.forge.token().expose_secret();
let net = given::a_network();
let mock_net = given::a_network();
net.on()
mock_net
.on()
.get(format!(
"https://{hostname}/api/v1/repos/{repo_path}/hooks?page=1&token={token}"
))
@ -286,9 +312,10 @@ mod forgejo {
.body("error_message")
.expect("mock");
let forge = given::a_forgejo_forge(&repo_details, net);
let forge = given::a_forgejo_forge(&repo_details, mock_net.clone());
let_assert!(Err(_) = forge.list_webhooks(&repo_listen_url).await);
mock_net.assert_no_unused_plans();
}
}
@ -303,9 +330,10 @@ mod forgejo {
let repo_path = &repo_details.repo_path;
let token = repo_details.forge.token().expose_secret();
let webhook_id = given::a_webhook_id();
let net = given::a_network();
let mock_net = given::a_network();
net.on()
mock_net
.on()
.delete(format!(
"https://{hostname}/api/v1/repos/{repo_path}/hooks/{webhook_id}?token={token}"
))
@ -313,9 +341,10 @@ mod forgejo {
.body("")
.expect("mock");
let forge = given::a_forgejo_forge(&repo_details, net);
let forge = given::a_forgejo_forge(&repo_details, mock_net.clone());
let_assert!(Ok(()) = forge.unregister_webhook(&webhook_id).await);
mock_net.assert_no_unused_plans();
}
#[tokio::test]
@ -326,9 +355,10 @@ mod forgejo {
let repo_path = &repo_details.repo_path;
let token = repo_details.forge.token().expose_secret();
let webhook_id = given::a_webhook_id();
let net = given::a_network();
let mock_net = given::a_network();
net.on()
mock_net
.on()
.delete(format!(
"https://{hostname}/api/v1/repos/{repo_path}/hooks/{webhook_id}?token={token}"
))
@ -336,13 +366,14 @@ mod forgejo {
.body("error")
.expect("mock");
let forge = given::a_forgejo_forge(&repo_details, net);
let forge = given::a_forgejo_forge(&repo_details, mock_net.clone());
let_assert!(Err(err) = forge.unregister_webhook(&webhook_id).await);
assert!(
matches!(err, git::forge::webhook::Error::FailedToUnregister(_)),
"{err:?}"
);
mock_net.assert_no_unused_plans();
}
}
@ -362,9 +393,9 @@ mod forgejo {
let repo_path = &repo_details.repo_path;
let token = repo_details.forge.token().expose_secret();
let mut net = given::a_network();
let mock_net = given::a_network();
let mut args = with::WebhookArgs {
net: &mut net,
mock_net: &mock_net,
hostname,
repo_path,
token,
@ -374,7 +405,8 @@ mod forgejo {
with::get_webhooks_by_page(1, &[], &mut args);
// register the webhook will succeed
let webhook_id = given::a_forgejo_webhook_id();
net.on()
mock_net
.on()
.post(format!(
"https://{hostname}/api/v1/repos/{repo_path}/hooks?token={token}"
))
@ -382,13 +414,14 @@ mod forgejo {
.body(json!({"id": webhook_id, "config":{}}).to_string())
.expect("mock");
let forge = given::a_forgejo_forge(&repo_details, net);
let forge = given::a_forgejo_forge(&repo_details, mock_net.clone());
let_assert!(Ok(registered_webhook) = forge.register_webhook(&repo_listen_url).await);
assert_eq!(
registered_webhook.id(),
&WebhookId::new(format!("{webhook_id}"))
);
mock_net.assert_no_unused_plans();
}
#[tokio::test]
@ -401,13 +434,14 @@ mod forgejo {
"repo_details needs to NOT have repo_config for this test"
);
let repo_listen_url = given::a_repo_listen_url(&repo_details);
let net = given::a_network();
let forge = given::a_forgejo_forge(&repo_details, net);
let mock_net = given::a_network();
let forge = given::a_forgejo_forge(&repo_details, mock_net.clone());
let_assert!(Err(err) = forge.register_webhook(&repo_listen_url).await);
assert!(
matches!(err, git::forge::webhook::Error::NoRepoConfig),
"{err:?}"
);
mock_net.assert_no_unused_plans();
}
#[tokio::test]
@ -423,9 +457,9 @@ mod forgejo {
let repo_path = &repo_details.repo_path;
let token = repo_details.forge.token().expose_secret();
let mut net = given::a_network();
let mock_net = given::a_network();
let mut args = with::WebhookArgs {
net: &mut net,
mock_net: &mock_net,
hostname,
repo_path,
token,
@ -448,7 +482,8 @@ mod forgejo {
with::unregister_webhook(&hooks[1], &mut args);
// register the webhook will succeed
let webhook_id = given::a_forgejo_webhook_id();
net.on()
mock_net
.on()
.post(format!(
"https://{hostname}/api/v1/repos/{repo_path}/hooks?token={token}"
))
@ -456,13 +491,14 @@ mod forgejo {
.body(json!({"id": webhook_id, "config":{}}).to_string())
.expect("mock");
let forge = given::a_forgejo_forge(&repo_details, net);
let forge = given::a_forgejo_forge(&repo_details, mock_net.clone());
let_assert!(Ok(registered_webhook) = forge.register_webhook(&repo_listen_url).await);
assert_eq!(
registered_webhook.id(),
&WebhookId::new(format!("{webhook_id}"))
);
mock_net.assert_no_unused_plans();
}
#[tokio::test]
@ -478,9 +514,9 @@ mod forgejo {
let repo_path = &repo_details.repo_path;
let token = repo_details.forge.token().expose_secret();
let mut net = given::a_network();
let mock_net = given::a_network();
let mut args = with::WebhookArgs {
net: &mut net,
mock_net: &mock_net,
hostname,
repo_path,
token,
@ -489,7 +525,8 @@ mod forgejo {
// there are no existing matching webhooks
with::get_webhooks_by_page(1, &[], &mut args);
// register the webhook will return empty response
net.on()
mock_net
.on()
.post(format!(
"https://{hostname}/api/v1/repos/{repo_path}/hooks?token={token}"
))
@ -497,13 +534,14 @@ mod forgejo {
.body(json!({}).to_string()) // empty response)
.expect("mock");
let forge = given::a_forgejo_forge(&repo_details, net);
let forge = given::a_forgejo_forge(&repo_details, mock_net.clone());
let_assert!(Err(err) = forge.register_webhook(&repo_listen_url).await);
assert!(
matches!(err, git::forge::webhook::Error::NetworkResponseEmpty),
"{err:?}"
);
mock_net.assert_no_unused_plans();
}
#[tokio::test]
@ -519,9 +557,9 @@ mod forgejo {
let repo_path = &repo_details.repo_path;
let token = repo_details.forge.token().expose_secret();
let mut net = given::a_network();
let mock_net = given::a_network();
let mut args = with::WebhookArgs {
net: &mut net,
mock_net: &mock_net,
hostname,
repo_path,
token,
@ -530,7 +568,8 @@ mod forgejo {
// there are no existing matching webhooks
with::get_webhooks_by_page(1, &[], &mut args);
// register the webhook will return empty response
net.on()
mock_net
.on()
.post(format!(
"https://{hostname}/api/v1/repos/{repo_path}/hooks?token={token}"
))
@ -538,13 +577,14 @@ mod forgejo {
.body("error")
.expect("mock");
let forge = given::a_forgejo_forge(&repo_details, net);
let forge = given::a_forgejo_forge(&repo_details, mock_net.clone());
let_assert!(Err(err) = forge.register_webhook(&repo_listen_url).await);
assert!(
matches!(err, git::forge::webhook::Error::FailedToRegister(_)),
"{err:?}"
);
mock_net.assert_no_unused_plans();
}
}
mod with {
@ -559,7 +599,7 @@ mod forgejo {
let hostname = args.hostname;
let repo_path = args.repo_path;
let token = args.token;
args.net
args.mock_net
.on()
.get(format!(
"https://{hostname}/api/v1/repos/{repo_path}/hooks?page={page}&token={token}"
@ -573,7 +613,7 @@ mod forgejo {
let hostname = args.hostname;
let repo_path = args.repo_path;
let token = args.token;
args.net
args.mock_net
.on()
.delete(format!(
"https://{hostname}/api/v1/repos/{repo_path}/hooks/{webhook_id}?token={token}"
@ -583,7 +623,7 @@ mod forgejo {
.expect("mock");
}
pub struct WebhookArgs<'a> {
pub net: &'a MockNet,
pub mock_net: &'a MockNet,
pub hostname: &'a Hostname,
pub repo_path: &'a RepoPath,
pub token: &'a str,

View file

@ -23,8 +23,10 @@ mod github {
#[test]
fn should_return_name() {
let forge = given::a_github_forge(&given::repo_details(), given::a_network());
let mock_net = given::a_network();
let forge = given::a_github_forge(&given::repo_details(), mock_net.clone());
assert_eq!(forge.name(), "github");
mock_net.assert_no_unused_plans();
}
mod is_message_authorised {
@ -33,27 +35,33 @@ mod github {
#[test]
fn should_return_true_with_valid_header() {
let forge = given::a_github_forge(&given::repo_details(), given::a_network());
let mock_net = given::a_network();
let forge = given::a_github_forge(&given::repo_details(), mock_net.clone());
let auth = given::a_webhook_auth();
let message = given::a_webhook_message(given::Header::Valid(
auth.clone(),
given::a_webhook_message_body(),
));
assert!(forge.is_message_authorised(&message, &auth));
mock_net.assert_no_unused_plans();
}
#[test]
fn should_return_false_with_missing_header() {
let forge = given::a_github_forge(&given::repo_details(), given::a_network());
let mock_net = given::a_network();
let forge = given::a_github_forge(&given::repo_details(), mock_net.clone());
let auth = given::a_webhook_auth();
let message = given::a_webhook_message(given::Header::Missing);
assert!(!forge.is_message_authorised(&message, &auth));
mock_net.assert_no_unused_plans();
}
#[test]
fn should_return_false_with_invalid_header() {
let forge = given::a_github_forge(&given::repo_details(), given::a_network());
let mock_net = given::a_network();
let forge = given::a_github_forge(&given::repo_details(), mock_net.clone());
let auth = given::a_webhook_auth();
let message = given::a_webhook_message(given::Header::Invalid);
assert!(!forge.is_message_authorised(&message, &auth));
mock_net.assert_no_unused_plans();
}
}
@ -63,7 +71,8 @@ mod github {
#[test]
fn should_parse_valid_body() {
let forge = given::a_github_forge(&given::repo_details(), given::a_network());
let mock_net = given::a_network();
let forge = given::a_github_forge(&given::repo_details(), mock_net.clone());
let repo_branches = given::repo_branches();
let next = repo_branches.next();
let sha = given::a_name();
@ -79,13 +88,16 @@ mod github {
push.branch(&repo_branches),
Some(webhook::push::Branch::Next)
);
mock_net.assert_no_unused_plans();
}
#[test]
fn should_error_invalid_body() {
let forge = given::a_github_forge(&given::repo_details(), given::a_network());
let mock_net = given::a_network();
let forge = given::a_github_forge(&given::repo_details(), mock_net.clone());
let body = Body::new(r#"{"type":"invalid"}"#.to_string());
let_assert!(Err(_) = forge.parse_webhook_body(&body));
mock_net.assert_no_unused_plans();
}
}
@ -101,10 +113,11 @@ mod github {
let (states, expected) = $value;
let repo_details = given::repo_details();
let commit = given::a_commit();
let net = given::a_network();
given::commit_states(&states, &net, &repo_details, &commit);
let forge = given::a_github_forge(&repo_details, net);
let mock_net = given::a_network();
given::commit_states(&states, &mock_net, &repo_details, &commit);
let forge = given::a_github_forge(&repo_details, mock_net.clone());
assert_eq!(forge.commit_status(&commit).await.expect("status"), expected);
mock_net.assert_no_unused_plans();
}
)*
}
@ -130,34 +143,38 @@ mod github {
async fn should_return_pass_for_no_statuses() {
let repo_details = given::repo_details();
let commit = given::a_commit();
let net = given::a_network();
net.on()
let mock_net = given::a_network();
mock_net
.on()
.get(given::a_commit_status_url(&repo_details, &commit))
.respond(StatusCode::OK)
.body(json!([]).to_string())
.expect("mock");
let forge = given::a_github_forge(&repo_details, net);
let forge = given::a_github_forge(&repo_details, mock_net.clone());
assert_eq!(
forge.commit_status(&commit).await.expect("status"),
Status::Pass // no CI checks configured
);
mock_net.assert_no_unused_plans();
}
#[tokio::test]
async fn should_return_pending_for_network_error() {
let repo_details = given::repo_details();
let commit = given::a_commit();
let net = given::a_network();
net.on()
let mock_net = given::a_network();
mock_net
.on()
.get(given::a_commit_status_url(&repo_details, &commit))
.respond(StatusCode::INTERNAL_SERVER_ERROR)
.body("boom today")
.expect("mock");
let forge = given::a_github_forge(&repo_details, net);
let forge = given::a_github_forge(&repo_details, mock_net.clone());
assert_eq!(
forge.commit_status(&commit).await.expect("status"),
Status::Pending
);
mock_net.assert_no_unused_plans();
}
}
@ -174,9 +191,9 @@ mod github {
let hook_id_1 = given::a_github_webhook_id();
let hook_id_2 = given::a_github_webhook_id();
let hook_id_3 = given::a_github_webhook_id();
let net = given::a_network();
let mock_net = given::a_network();
let args = with::WebhookArgs {
net: &net,
mock_net: &mock_net,
hostname,
repo_path,
};
@ -193,7 +210,7 @@ mod github {
// page 2 with no items - stops pagination
with::get_webhooks_by_page(2, &[], &args);
let forge = given::a_github_forge(&repo_details, net);
let forge = given::a_github_forge(&repo_details, mock_net.clone());
let_assert!(Ok(result) = forge.list_webhooks(&repo_listen_url).await);
assert_eq!(
@ -203,6 +220,7 @@ mod github {
WebhookId::new(format!("{hook_id_2}"))
]
);
mock_net.assert_no_unused_plans();
}
#[tokio::test]
@ -211,8 +229,9 @@ mod github {
let repo_listen_url = given::a_repo_listen_url(&repo_details);
let hostname = repo_details.forge.hostname();
let repo_path = &repo_details.repo_path;
let net = given::a_network();
net.on()
let mock_net = given::a_network();
mock_net
.on()
.get(format!(
"https://api.{hostname}/repos/{repo_path}/hooks?page=1"
))
@ -220,9 +239,10 @@ mod github {
.body("error_message")
.expect("mock");
let forge = given::a_github_forge(&repo_details, net);
let forge = given::a_github_forge(&repo_details, mock_net.clone());
let_assert!(Err(_) = forge.list_webhooks(&repo_listen_url).await);
mock_net.assert_no_unused_plans();
}
}
@ -235,8 +255,9 @@ mod github {
let hostname = repo_details.forge.hostname();
let repo_path = &repo_details.repo_path;
let webhook_id = given::a_webhook_id();
let net = given::a_network();
net.on()
let mock_net = given::a_network();
mock_net
.on()
.delete(format!(
"https://api.{hostname}/repos/{repo_path}/hooks/{webhook_id}"
))
@ -244,9 +265,10 @@ mod github {
.body("")
.expect("mock");
let forge = given::a_github_forge(&repo_details, net);
let forge = given::a_github_forge(&repo_details, mock_net.clone());
let_assert!(Ok(()) = forge.unregister_webhook(&webhook_id).await);
mock_net.assert_no_unused_plans();
}
#[tokio::test]
async fn should_return_error_on_network_error() {
@ -257,10 +279,11 @@ mod github {
);
let hostname = repo_details.forge.hostname();
let repo_path = &repo_details.repo_path;
let net = given::a_network();
let mock_net = given::a_network();
// unregister the webhook will return empty response
let webhook_id = given::a_webhook_id();
net.on()
mock_net
.on()
.delete(format!(
"https://api.{hostname}/repos/{repo_path}/hooks/{webhook_id}"
))
@ -268,13 +291,14 @@ mod github {
.mock()
.expect("mock");
let forge = given::a_github_forge(&repo_details, net);
let forge = given::a_github_forge(&repo_details, mock_net.clone());
let_assert!(Err(err) = forge.unregister_webhook(&webhook_id).await);
assert!(
matches!(err, git::forge::webhook::Error::FailedToRegister(_)),
"{err:?}"
);
mock_net.assert_no_unused_plans();
}
}
@ -292,9 +316,9 @@ mod github {
let repo_listen_url = given::a_repo_listen_url(&repo_details);
let hostname = repo_details.forge.hostname();
let repo_path = &repo_details.repo_path;
let net = given::a_network();
let mock_net = given::a_network();
let args = with::WebhookArgs {
net: &net,
mock_net: &mock_net,
hostname,
repo_path,
};
@ -302,7 +326,8 @@ mod github {
with::get_webhooks_by_page(1, &[], &args);
// register the webhook will succeed
let webhook_id = given::a_github_webhook_id();
net.on()
mock_net
.on()
.post(format!("https://api.{hostname}/repos/{repo_path}/hooks"))
.respond(StatusCode::OK)
.body(
@ -311,13 +336,14 @@ mod github {
)
.expect("mock");
let forge = given::a_github_forge(&repo_details, net);
let forge = given::a_github_forge(&repo_details, mock_net.clone());
let_assert!(Ok(registered_webhook) = forge.register_webhook(&repo_listen_url).await);
assert_eq!(
registered_webhook.id(),
&WebhookId::new(format!("{webhook_id}"))
);
mock_net.assert_no_unused_plans();
}
#[tokio::test]
@ -329,13 +355,14 @@ mod github {
"repo_details needs to NOT have repo_config for this test"
);
let repo_listen_url = given::a_repo_listen_url(&repo_details);
let net = given::a_network();
let forge = given::a_github_forge(&repo_details, net);
let mock_net = given::a_network();
let forge = given::a_github_forge(&repo_details, mock_net.clone());
let_assert!(Err(err) = forge.register_webhook(&repo_listen_url).await);
assert!(
matches!(err, git::forge::webhook::Error::NoRepoConfig),
"{err:?}"
);
mock_net.assert_no_unused_plans();
}
#[tokio::test]
@ -348,9 +375,9 @@ mod github {
let repo_listen_url = given::a_repo_listen_url(&repo_details);
let hostname = repo_details.forge.hostname();
let repo_path = &repo_details.repo_path;
let net = given::a_network();
let mock_net = given::a_network();
let args = with::WebhookArgs {
net: &net,
mock_net: &mock_net,
hostname,
repo_path,
};
@ -367,7 +394,8 @@ mod github {
with::unregister_webhook(&hooks[1], &args);
// register the webhook will succeed
let webhook_id = given::a_github_webhook_id();
net.on()
mock_net
.on()
.post(format!("https://api.{hostname}/repos/{repo_path}/hooks"))
.respond(StatusCode::OK)
.body(
@ -376,13 +404,14 @@ mod github {
)
.expect("mock");
let forge = given::a_github_forge(&repo_details, net);
let forge = given::a_github_forge(&repo_details, mock_net.clone());
let_assert!(Ok(registered_webhook) = forge.register_webhook(&repo_listen_url).await);
assert_eq!(
registered_webhook.id(),
&WebhookId::new(format!("{webhook_id}"))
);
mock_net.assert_no_unused_plans();
}
#[tokio::test]
@ -395,28 +424,30 @@ mod github {
let repo_listen_url = given::a_repo_listen_url(&repo_details);
let hostname = repo_details.forge.hostname();
let repo_path = &repo_details.repo_path;
let net = given::a_network();
let mock_net = given::a_network();
let args = with::WebhookArgs {
net: &net,
mock_net: &mock_net,
hostname,
repo_path,
};
// there are no existing matching webhooks
with::get_webhooks_by_page(1, &[], &args);
// register the webhook will return empty response
net.on()
mock_net
.on()
.post(format!("https://api.{hostname}/repos/{repo_path}/hooks"))
.respond(StatusCode::OK)
.body(json!({}).to_string())
.expect("mock");
let forge = given::a_github_forge(&repo_details, net);
let forge = given::a_github_forge(&repo_details, mock_net.clone());
let_assert!(Err(err) = forge.register_webhook(&repo_listen_url).await);
assert!(
matches!(err, git::forge::webhook::Error::NetworkResponseEmpty),
"{err:?}"
);
mock_net.assert_no_unused_plans();
}
#[tokio::test]
@ -429,28 +460,30 @@ mod github {
let repo_listen_url = given::a_repo_listen_url(&repo_details);
let hostname = repo_details.forge.hostname();
let repo_path = &repo_details.repo_path;
let net = given::a_network();
let mock_net = given::a_network();
let args = with::WebhookArgs {
net: &net,
mock_net: &mock_net,
hostname,
repo_path,
};
// there are no existing matching webhooks
with::get_webhooks_by_page(1, &[], &args);
// register the webhook will return empty response
net.on()
mock_net
.on()
.post(format!("https://api.{hostname}/repos/{repo_path}/hooks"))
.respond(StatusCode::INTERNAL_SERVER_ERROR)
.body("error")
.expect("mock");
let forge = given::a_github_forge(&repo_details, net);
let forge = given::a_github_forge(&repo_details, mock_net.clone());
let_assert!(Err(err) = forge.register_webhook(&repo_listen_url).await);
assert!(
matches!(err, git::forge::webhook::Error::FailedToRegister(_)),
"{err:?}"
);
mock_net.assert_no_unused_plans();
}
}
@ -462,7 +495,7 @@ mod github {
pub fn get_webhooks_by_page(page: u8, response: &[ReturnedWebhook], args: &WebhookArgs) {
let hostname = args.hostname;
let repo_path = args.repo_path;
args.net
args.mock_net
.on()
.get(format!(
"https://api.{hostname}/repos/{repo_path}/hooks?page={page}"
@ -476,7 +509,7 @@ mod github {
let webhook_id = hook1.id;
let hostname = args.hostname;
let repo_path = args.repo_path;
args.net
args.mock_net
.on()
.delete(format!(
"https://api.{hostname}/repos/{repo_path}/hooks/{webhook_id}"
@ -486,7 +519,7 @@ mod github {
.expect("mock");
}
pub struct WebhookArgs<'a> {
pub net: &'a kxio::net::MockNet,
pub mock_net: &'a kxio::net::MockNet,
pub hostname: &'a Hostname,
pub repo_path: &'a RepoPath,
}

2
mise.linux.toml Normal file
View file

@ -0,0 +1,2 @@
[tools]
"cargo:cargo-hack" = "latest"