use super::*;
use crate::negotiation::Protocol;
use crate::task::{NewTaskOpts, Task};
use tempfile::tempdir;
fn stealth_store_with_task(claimer: &str) -> (tempfile::TempDir, Store, String) {
let td = tempdir().unwrap();
let tasks_dir = td.path().join("tasks");
let store = Store::init(
td.path(),
true,
Some(tasks_dir.to_string_lossy().into_owned()),
)
.unwrap();
let mut task = Task::new(NewTaskOpts { title: "t".into(), ..Default::default() }, "bl-7e57".into());
task.claimed_by = Some(claimer.into());
store.save_task(&task).unwrap();
(td, store, "bl-7e57".into())
}
#[test]
fn post_merge_returns_none_when_we_still_own_claim() {
let (_td, store, id) = stealth_store_with_task("alice");
let mut p = GitRemoteClaimProtocol::new(Event::Claim, &store, &id, "alice");
assert!(p.post_merge().unwrap().is_none());
}
#[test]
fn post_merge_returns_lost_with_unknown_winner_when_claim_cleared() {
let (_td, store, id) = stealth_store_with_task("");
let mut task = store.load_task(&id).unwrap();
task.claimed_by = None;
store.save_task(&task).unwrap();
let mut p = GitRemoteClaimProtocol::new(Event::Claim, &store, &id, "alice");
let outcome = p.post_merge().unwrap().unwrap();
assert_eq!(outcome, SyncedClaimResult::Lost { winner: "(unknown)".into() });
}
#[test]
fn post_merge_skips_ownership_check_for_review_and_close() {
let (_td, store, id) = stealth_store_with_task("");
let mut task = store.load_task(&id).unwrap();
task.claimed_by = None;
store.save_task(&task).unwrap();
for ev in [Event::Review, Event::Close] {
let mut p = GitRemoteClaimProtocol::new(ev, &store, &id, "alice");
assert!(
p.post_merge().unwrap().is_none(),
"{ev:?} post_merge should never short-circuit"
);
}
}
use crate::participant::{Event, Participant, Projection};
#[test]
fn participant_advertises_git_remote_name_and_full_projection() {
let p = GitRemoteParticipant::for_claim();
assert_eq!(p.name(), "git-remote");
assert_eq!(p.subscriptions(), &[Event::Claim]);
assert_eq!(*p.projection(), Projection::full());
}
#[test]
fn participant_default_matches_for_claim() {
let a = GitRemoteParticipant::default();
let b = GitRemoteParticipant::for_claim();
assert_eq!(a.subscriptions(), b.subscriptions());
assert_eq!(*a.projection(), *b.projection());
}
#[test]
fn participant_failure_policy_required_for_subscribed_events() {
let p = GitRemoteParticipant::for_claim();
assert_eq!(p.failure_policy(Event::Claim), FailurePolicy::Required);
for e in [Event::Review, Event::Close, Event::Update, Event::Sync] {
assert_eq!(p.failure_policy(e), FailurePolicy::BestEffort);
}
let p = GitRemoteParticipant::for_lifecycle(&[Event::Review, Event::Close]);
assert_eq!(p.failure_policy(Event::Review), FailurePolicy::Required);
assert_eq!(p.failure_policy(Event::Close), FailurePolicy::Required);
assert_eq!(p.failure_policy(Event::Claim), FailurePolicy::BestEffort);
}
#[test]
fn participant_protocol_is_some_for_lifecycle_events() {
let (_td, store, id) = stealth_store_with_task("alice");
let p = GitRemoteParticipant::for_claim();
let mk = |event| crate::participant::EventCtx::new(event, &store, &id, "alice");
assert!(p.protocol(Event::Claim, mk(Event::Claim)).is_some());
for e in [Event::Review, Event::Close] {
assert!(p.protocol(e, mk(e)).is_some(), "{e:?}");
}
for e in [Event::Update, Event::Sync] {
assert!(p.protocol(e, mk(e)).is_none(), "{e:?}");
}
}