use pezframe_support::{assert_noop, assert_ok};
use pezframe_system::{EventRecord, Phase};
use pezsp_runtime::traits::BadOrigin;
use super::*;
use crate::{self as alliance, mock::*};
type AllianceMotionEvent = pezpallet_collective::Event<Test, pezpallet_collective::Instance1>;
fn assert_powerless(user: RuntimeOrigin, user_is_member: bool) {
let cid = test_cid();
let (proposal, _, _) = make_kick_member_proposal(42);
assert_noop!(Alliance::init_members(user.clone(), vec![], vec![],), BadOrigin);
assert_noop!(
Alliance::disband(user.clone(), DisbandWitness { fellow_members: 3, ..Default::default() }),
BadOrigin
);
assert_noop!(Alliance::set_rule(user.clone(), cid.clone()), BadOrigin);
assert_noop!(Alliance::retire(user.clone()), Error::<Test, ()>::RetirementNoticeNotGiven);
if !user_is_member {
assert_noop!(Alliance::give_retirement_notice(user.clone()), Error::<Test, ()>::NotMember);
}
assert_noop!(Alliance::elevate_ally(user.clone(), 4), BadOrigin);
assert_noop!(Alliance::kick_member(user.clone(), 1), BadOrigin);
assert_noop!(Alliance::nominate_ally(user.clone(), 4), Error::<Test, ()>::NoVotingRights);
assert_noop!(
Alliance::propose(user.clone(), 5, Box::new(proposal), 1000),
Error::<Test, ()>::NoVotingRights
);
}
#[test]
fn init_members_works() {
build_and_execute(|| {
assert_noop!(
Alliance::init_members(RuntimeOrigin::root(), vec![8], vec![],),
Error::<Test, ()>::AllianceAlreadyInitialized,
);
assert_ok!(Alliance::give_retirement_notice(RuntimeOrigin::signed(2)));
assert!(Alliance::is_member_of(&2, MemberRole::Retiring));
assert_ok!(Alliance::disband(RuntimeOrigin::root(), DisbandWitness::new(2, 0)));
assert_noop!(Alliance::init_members(RuntimeOrigin::signed(1), vec![], vec![]), BadOrigin);
assert_noop!(
Alliance::init_members(RuntimeOrigin::root(), vec![], vec![2],),
Error::<Test, ()>::FellowsMissing,
);
assert_ok!(Alliance::init_members(RuntimeOrigin::root(), vec![8, 5], vec![2],));
assert_eq!(Alliance::voting_members(), vec![5, 8]);
assert!(is_fellow(&8));
assert!(is_fellow(&5));
assert!(Alliance::is_ally(&2));
assert!(Alliance::is_member_of(&2, MemberRole::Retiring));
System::assert_last_event(mock::RuntimeEvent::Alliance(crate::Event::MembersInitialized {
fellows: vec![5, 8],
allies: vec![2],
}));
})
}
#[test]
fn disband_works() {
build_and_execute(|| {
let id_deposit = test_identity_info_deposit();
let expected_join_deposit = <Test as Config>::AllyDeposit::get();
assert_eq!(Balances::free_balance(9), 1000 - id_deposit);
assert_eq!(Alliance::voting_members(), vec![1, 2, 3]);
assert_ok!(Alliance::give_retirement_notice(RuntimeOrigin::signed(2)));
assert!(Alliance::is_member_of(&2, MemberRole::Retiring));
assert_eq!(Balances::free_balance(9), 1000 - id_deposit);
assert_ok!(Alliance::join_alliance(RuntimeOrigin::signed(9)));
assert_eq!(alliance::DepositOf::<Test>::get(9), Some(expected_join_deposit));
assert_eq!(Balances::free_balance(9), 1000 - id_deposit - expected_join_deposit);
assert!(Alliance::is_member_of(&9, MemberRole::Ally));
assert_noop!(Alliance::disband(RuntimeOrigin::signed(1), Default::default()), BadOrigin);
assert_noop!(
Alliance::disband(RuntimeOrigin::root(), Default::default(),),
Error::<Test, ()>::BadWitness
);
assert_noop!(
Alliance::disband(RuntimeOrigin::root(), DisbandWitness::new(1, 1)),
Error::<Test, ()>::BadWitness,
);
assert_noop!(
Alliance::disband(RuntimeOrigin::root(), DisbandWitness::new(2, 0)),
Error::<Test, ()>::BadWitness,
);
assert_ok!(Alliance::disband(RuntimeOrigin::root(), DisbandWitness::new(2, 1)));
assert!(!Alliance::is_member(&1));
assert!(!Alliance::is_initialized());
assert!(Alliance::is_member_of(&2, MemberRole::Retiring));
assert_eq!(Balances::free_balance(9), 1000 - id_deposit);
System::assert_last_event(mock::RuntimeEvent::Alliance(crate::Event::AllianceDisbanded {
fellow_members: 2,
ally_members: 1,
unreserved: 1,
}));
assert_noop!(
Alliance::disband(RuntimeOrigin::root(), DisbandWitness::new(100, 100)),
Error::<Test, ()>::AllianceNotYetInitialized,
);
})
}
#[test]
fn propose_works() {
build_and_execute(|| {
let (proposal, proposal_len, hash) = make_remark_proposal(42);
assert_noop!(
Alliance::propose(
RuntimeOrigin::signed(4),
3,
Box::new(proposal.clone()),
proposal_len
),
Error::<Test, ()>::NoVotingRights
);
assert_ok!(Alliance::propose(
RuntimeOrigin::signed(1),
3,
Box::new(proposal.clone()),
proposal_len
));
assert_eq!(*pezpallet_collective::Proposals::<Test, Instance1>::get(), vec![hash]);
assert_eq!(pezpallet_collective::ProposalOf::<Test, Instance1>::get(&hash), Some(proposal));
assert_eq!(
System::events(),
vec![EventRecord {
phase: Phase::Initialization,
event: mock::RuntimeEvent::AllianceMotion(AllianceMotionEvent::Proposed {
account: 1,
proposal_index: 0,
proposal_hash: hash,
threshold: 3,
}),
topics: vec![],
}]
);
});
}
#[test]
fn vote_works() {
build_and_execute(|| {
let (proposal, proposal_len, hash) = make_remark_proposal(42);
assert_ok!(Alliance::propose(
RuntimeOrigin::signed(1),
3,
Box::new(proposal.clone()),
proposal_len
));
assert_ok!(Alliance::vote(RuntimeOrigin::signed(2), hash, 0, true));
let record = |event| EventRecord { phase: Phase::Initialization, event, topics: vec![] };
assert_eq!(
System::events(),
vec![
record(mock::RuntimeEvent::AllianceMotion(AllianceMotionEvent::Proposed {
account: 1,
proposal_index: 0,
proposal_hash: hash,
threshold: 3
})),
record(mock::RuntimeEvent::AllianceMotion(AllianceMotionEvent::Voted {
account: 2,
proposal_hash: hash,
voted: true,
yes: 1,
no: 0,
})),
]
);
});
}
#[test]
fn close_works() {
build_and_execute(|| {
let (proposal, proposal_len, hash) = make_remark_proposal(42);
let proposal_weight = proposal.get_dispatch_info().call_weight;
assert_ok!(Alliance::propose(
RuntimeOrigin::signed(1),
3,
Box::new(proposal.clone()),
proposal_len
));
assert_ok!(Alliance::vote(RuntimeOrigin::signed(1), hash, 0, true));
assert_ok!(Alliance::vote(RuntimeOrigin::signed(2), hash, 0, true));
assert_ok!(Alliance::vote(RuntimeOrigin::signed(3), hash, 0, true));
assert_ok!(Alliance::close(
RuntimeOrigin::signed(1),
hash,
0,
proposal_weight,
proposal_len
));
let record = |event| EventRecord { phase: Phase::Initialization, event, topics: vec![] };
assert_eq!(
System::events(),
vec![
record(mock::RuntimeEvent::AllianceMotion(AllianceMotionEvent::Proposed {
account: 1,
proposal_index: 0,
proposal_hash: hash,
threshold: 3
})),
record(mock::RuntimeEvent::AllianceMotion(AllianceMotionEvent::Voted {
account: 1,
proposal_hash: hash,
voted: true,
yes: 1,
no: 0,
})),
record(mock::RuntimeEvent::AllianceMotion(AllianceMotionEvent::Voted {
account: 2,
proposal_hash: hash,
voted: true,
yes: 2,
no: 0,
})),
record(mock::RuntimeEvent::AllianceMotion(AllianceMotionEvent::Voted {
account: 3,
proposal_hash: hash,
voted: true,
yes: 3,
no: 0,
})),
record(mock::RuntimeEvent::AllianceMotion(AllianceMotionEvent::Closed {
proposal_hash: hash,
yes: 3,
no: 0,
})),
record(mock::RuntimeEvent::AllianceMotion(AllianceMotionEvent::Approved {
proposal_hash: hash
})),
record(mock::RuntimeEvent::AllianceMotion(AllianceMotionEvent::Executed {
proposal_hash: hash,
result: Ok(()),
}))
]
);
});
}
#[test]
fn set_rule_works() {
build_and_execute(|| {
let cid = test_cid();
assert_ok!(Alliance::set_rule(RuntimeOrigin::signed(1), cid.clone()));
assert_eq!(alliance::Rule::<Test>::get(), Some(cid.clone()));
System::assert_last_event(mock::RuntimeEvent::Alliance(crate::Event::NewRuleSet {
rule: cid,
}));
});
}
#[test]
fn announce_works() {
build_and_execute(|| {
let cid = test_cid();
assert_noop!(Alliance::announce(RuntimeOrigin::signed(2), cid.clone()), BadOrigin);
assert_ok!(Alliance::announce(RuntimeOrigin::signed(3), cid.clone()));
assert_eq!(alliance::Announcements::<Test>::get(), vec![cid.clone()]);
System::assert_last_event(mock::RuntimeEvent::Alliance(crate::Event::Announced {
announcement: cid,
}));
});
}
#[test]
fn remove_announcement_works() {
build_and_execute(|| {
let cid = test_cid();
assert_ok!(Alliance::announce(RuntimeOrigin::signed(3), cid.clone()));
assert_eq!(alliance::Announcements::<Test>::get(), vec![cid.clone()]);
System::assert_last_event(mock::RuntimeEvent::Alliance(crate::Event::Announced {
announcement: cid.clone(),
}));
System::set_block_number(2);
assert_ok!(Alliance::remove_announcement(RuntimeOrigin::signed(3), cid.clone()));
assert_eq!(alliance::Announcements::<Test>::get(), vec![]);
System::assert_last_event(mock::RuntimeEvent::Alliance(
crate::Event::AnnouncementRemoved { announcement: cid },
));
});
}
#[test]
fn join_alliance_works() {
build_and_execute(|| {
let id_deposit = test_identity_info_deposit();
let join_deposit = <Test as Config>::AllyDeposit::get();
assert_eq!(Balances::free_balance(9), 1000 - id_deposit);
assert_noop!(
Alliance::join_alliance(RuntimeOrigin::signed(1)),
Error::<Test, ()>::AlreadyMember
);
assert_ok!(Alliance::add_unscrupulous_items(
RuntimeOrigin::signed(3),
vec![UnscrupulousItem::AccountId(4)]
));
assert_noop!(
Alliance::join_alliance(RuntimeOrigin::signed(4)),
Error::<Test, ()>::AccountNonGrata
);
assert_ok!(Alliance::remove_unscrupulous_items(
RuntimeOrigin::signed(3),
vec![UnscrupulousItem::AccountId(4)]
));
assert_noop!(
Alliance::join_alliance(RuntimeOrigin::signed(5)),
Error::<Test, ()>::InsufficientFunds
);
assert_eq!(Balances::free_balance(4), 1000 - id_deposit);
assert_ok!(Alliance::join_alliance(RuntimeOrigin::signed(4)));
assert_eq!(Balances::free_balance(4), 1000 - id_deposit - join_deposit);
assert_eq!(alliance::DepositOf::<Test>::get(4), Some(25));
assert_eq!(alliance::Members::<Test>::get(MemberRole::Ally), vec![4]);
assert_noop!(
Alliance::join_alliance(RuntimeOrigin::signed(4)),
Error::<Test, ()>::AlreadyMember
);
#[cfg(not(feature = "runtime-benchmarks"))]
assert_noop!(
Alliance::join_alliance(RuntimeOrigin::signed(6)),
Error::<Test, ()>::WithoutGoodIdentityJudgement
);
#[cfg(not(feature = "runtime-benchmarks"))]
assert_noop!(
Alliance::join_alliance(RuntimeOrigin::signed(7)),
Error::<Test, ()>::WithoutRequiredIdentityFields
);
});
}
#[test]
fn nominate_ally_works() {
build_and_execute(|| {
assert_noop!(
Alliance::nominate_ally(RuntimeOrigin::signed(1), 2),
Error::<Test, ()>::AlreadyMember
);
assert_noop!(
Alliance::nominate_ally(RuntimeOrigin::signed(5), 4),
Error::<Test, ()>::NoVotingRights
);
assert_ok!(Alliance::add_unscrupulous_items(
RuntimeOrigin::signed(3),
vec![UnscrupulousItem::AccountId(4)]
));
assert_noop!(
Alliance::nominate_ally(RuntimeOrigin::signed(1), 4),
Error::<Test, ()>::AccountNonGrata
);
assert_ok!(Alliance::remove_unscrupulous_items(
RuntimeOrigin::signed(3),
vec![UnscrupulousItem::AccountId(4)]
));
assert_ok!(Alliance::nominate_ally(RuntimeOrigin::signed(1), 4));
assert_eq!(alliance::DepositOf::<Test>::get(4), None);
assert_eq!(alliance::Members::<Test>::get(MemberRole::Ally), vec![4]);
assert_noop!(
Alliance::nominate_ally(RuntimeOrigin::signed(1), 4),
Error::<Test, ()>::AlreadyMember
);
#[cfg(not(feature = "runtime-benchmarks"))]
assert_noop!(
Alliance::join_alliance(RuntimeOrigin::signed(6)),
Error::<Test, ()>::WithoutGoodIdentityJudgement
);
#[cfg(not(feature = "runtime-benchmarks"))]
assert_noop!(
Alliance::join_alliance(RuntimeOrigin::signed(7)),
Error::<Test, ()>::WithoutRequiredIdentityFields
);
});
}
#[test]
fn elevate_ally_works() {
build_and_execute(|| {
assert_noop!(
Alliance::elevate_ally(RuntimeOrigin::signed(2), 4),
Error::<Test, ()>::NotAlly
);
assert_ok!(Alliance::join_alliance(RuntimeOrigin::signed(4)));
assert_eq!(alliance::Members::<Test>::get(MemberRole::Ally), vec![4]);
assert_eq!(alliance::Members::<Test>::get(MemberRole::Fellow), vec![1, 2, 3]);
assert_ok!(Alliance::elevate_ally(RuntimeOrigin::signed(2), 4));
assert_eq!(alliance::Members::<Test>::get(MemberRole::Ally), Vec::<u64>::new());
assert_eq!(alliance::Members::<Test>::get(MemberRole::Fellow), vec![1, 2, 3, 4]);
});
}
#[test]
fn give_retirement_notice_work() {
build_and_execute(|| {
assert_noop!(
Alliance::give_retirement_notice(RuntimeOrigin::signed(4)),
Error::<Test, ()>::NotMember
);
assert_eq!(alliance::Members::<Test>::get(MemberRole::Fellow), vec![1, 2, 3]);
assert_ok!(Alliance::give_retirement_notice(RuntimeOrigin::signed(3)));
assert_eq!(alliance::Members::<Test>::get(MemberRole::Fellow), vec![1, 2]);
assert_eq!(alliance::Members::<Test>::get(MemberRole::Retiring), vec![3]);
System::assert_last_event(mock::RuntimeEvent::Alliance(
crate::Event::MemberRetirementPeriodStarted { member: (3) },
));
assert_noop!(
Alliance::give_retirement_notice(RuntimeOrigin::signed(3)),
Error::<Test, ()>::AlreadyRetiring
);
});
}
#[test]
fn retire_works() {
build_and_execute(|| {
assert_noop!(
Alliance::retire(RuntimeOrigin::signed(2)),
Error::<Test, ()>::RetirementNoticeNotGiven
);
assert_noop!(
Alliance::retire(RuntimeOrigin::signed(4)),
Error::<Test, ()>::RetirementNoticeNotGiven
);
assert_eq!(alliance::Members::<Test>::get(MemberRole::Fellow), vec![1, 2, 3]);
assert_ok!(Alliance::give_retirement_notice(RuntimeOrigin::signed(3)));
assert_noop!(
Alliance::retire(RuntimeOrigin::signed(3)),
Error::<Test, ()>::RetirementPeriodNotPassed
);
System::set_block_number(System::block_number() + RetirementPeriod::get());
assert_ok!(Alliance::retire(RuntimeOrigin::signed(3)));
assert_eq!(alliance::Members::<Test>::get(MemberRole::Fellow), vec![1, 2]);
System::assert_last_event(mock::RuntimeEvent::Alliance(crate::Event::MemberRetired {
member: (3),
unreserved: None,
}));
System::set_block_number(System::block_number() + RetirementPeriod::get());
assert_powerless(RuntimeOrigin::signed(3), false);
});
}
#[test]
fn abdicate_works() {
build_and_execute(|| {
assert_eq!(alliance::Members::<Test>::get(MemberRole::Fellow), vec![1, 2, 3]);
assert_ok!(Alliance::abdicate_fellow_status(RuntimeOrigin::signed(3)));
System::assert_last_event(mock::RuntimeEvent::Alliance(crate::Event::FellowAbdicated {
fellow: (3),
}));
assert_powerless(RuntimeOrigin::signed(3), true);
});
}
#[test]
fn kick_member_works() {
build_and_execute(|| {
assert_noop!(Alliance::kick_member(RuntimeOrigin::signed(4), 4), BadOrigin);
assert_noop!(
Alliance::kick_member(RuntimeOrigin::signed(2), 4),
Error::<Test, ()>::NotMember
);
<DepositOf<Test, ()>>::insert(2, 25);
assert_eq!(alliance::Members::<Test>::get(MemberRole::Fellow), vec![1, 2, 3]);
assert_ok!(Alliance::kick_member(RuntimeOrigin::signed(2), 2));
assert_eq!(alliance::Members::<Test>::get(MemberRole::Fellow), vec![1, 3]);
assert_eq!(<DepositOf<Test, ()>>::get(2), None);
System::assert_last_event(mock::RuntimeEvent::Alliance(crate::Event::MemberKicked {
member: (2),
slashed: Some(25),
}));
});
}
#[test]
fn add_unscrupulous_items_works() {
build_and_execute(|| {
assert_noop!(Alliance::add_unscrupulous_items(RuntimeOrigin::signed(2), vec![]), BadOrigin);
assert_ok!(Alliance::add_unscrupulous_items(
RuntimeOrigin::signed(3),
vec![
UnscrupulousItem::AccountId(3),
UnscrupulousItem::Website("abc".as_bytes().to_vec().try_into().unwrap())
]
));
assert_eq!(alliance::UnscrupulousAccounts::<Test>::get().into_inner(), vec![3]);
assert_eq!(
alliance::UnscrupulousWebsites::<Test>::get().into_inner(),
vec!["abc".as_bytes().to_vec()]
);
assert_noop!(
Alliance::add_unscrupulous_items(
RuntimeOrigin::signed(3),
vec![UnscrupulousItem::AccountId(3)]
),
Error::<Test, ()>::AlreadyUnscrupulous
);
});
}
#[test]
fn remove_unscrupulous_items_works() {
build_and_execute(|| {
assert_noop!(
Alliance::remove_unscrupulous_items(RuntimeOrigin::signed(2), vec![]),
BadOrigin
);
assert_noop!(
Alliance::remove_unscrupulous_items(
RuntimeOrigin::signed(3),
vec![UnscrupulousItem::AccountId(3)]
),
Error::<Test, ()>::NotListedAsUnscrupulous
);
assert_ok!(Alliance::add_unscrupulous_items(
RuntimeOrigin::signed(3),
vec![UnscrupulousItem::AccountId(3)]
));
assert_eq!(alliance::UnscrupulousAccounts::<Test>::get(), vec![3]);
assert_ok!(Alliance::remove_unscrupulous_items(
RuntimeOrigin::signed(3),
vec![UnscrupulousItem::AccountId(3)]
));
assert_eq!(alliance::UnscrupulousAccounts::<Test>::get(), Vec::<u64>::new());
});
}
#[test]
fn weights_sane() {
let info = crate::Call::<Test>::join_alliance {}.get_dispatch_info();
assert_eq!(<() as crate::WeightInfo>::join_alliance(), info.call_weight);
let info = crate::Call::<Test>::nominate_ally { who: 10 }.get_dispatch_info();
assert_eq!(<() as crate::WeightInfo>::nominate_ally(), info.call_weight);
}