123456789101112131415161718192021222324252627282930313233use crate as collator_selection;34use crate::{mock::*, Error};35use frame_support::{36 assert_noop, assert_ok,37 traits::{Currency, GenesisBuild, OnInitialize},38};39use frame_system::RawOrigin;40use pallet_balances::Error as BalancesError;41use sp_runtime::traits::BadOrigin;42use pallet_configuration::{43 CollatorSelectionDesiredCollatorsOverride as DesiredCollators,44 CollatorSelectionKickThresholdOverride as KickThreshold,45 CollatorSelectionLicenseBondOverride as LicenseBond,46};4748fn get_license_and_onboard(account_id: <Test as frame_system::Config>::AccountId) {49 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(50 account_id51 )));52 assert_ok!(CollatorSelection::onboard(RuntimeOrigin::signed(53 account_id54 )));55}5657#[test]58fn basic_setup_works() {59 new_test_ext().execute_with(|| {60 assert_eq!(<DesiredCollators<Test>>::get(), 5);61 assert_eq!(<LicenseBond<Test>>::get(), 10);6263 assert!(CollatorSelection::candidates().is_empty());64 assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);65 });66}6768#[test]69fn it_should_add_invulnerables() {70 new_test_ext().execute_with(|| {71 assert_ok!(CollatorSelection::add_invulnerable(72 RuntimeOrigin::signed(RootAccount::get()),73 174 ));75 assert_ok!(CollatorSelection::add_invulnerable(76 RuntimeOrigin::signed(RootAccount::get()),77 278 ));79 assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);8081 82 assert_noop!(83 CollatorSelection::add_invulnerable(RuntimeOrigin::signed(1), 3),84 BadOrigin85 );8687 88 assert_noop!(89 CollatorSelection::add_invulnerable(RuntimeOrigin::signed(RootAccount::get()), 7),90 Error::<Test>::ValidatorNotRegistered91 );92 });93}9495#[test]96fn it_should_remove_invulnerables() {97 new_test_ext().execute_with(|| {98 assert_ok!(CollatorSelection::add_invulnerable(99 RuntimeOrigin::signed(RootAccount::get()),100 1101 ));102 assert_ok!(CollatorSelection::add_invulnerable(103 RuntimeOrigin::signed(RootAccount::get()),104 2105 ));106107 108 assert_noop!(109 CollatorSelection::remove_invulnerable(RuntimeOrigin::signed(1), 3),110 BadOrigin111 );112113 assert_ok!(CollatorSelection::remove_invulnerable(114 RuntimeOrigin::signed(RootAccount::get()),115 2116 ));117 assert_eq!(CollatorSelection::invulnerables(), vec![1]);118119 120 assert_noop!(121 CollatorSelection::remove_invulnerable(RuntimeOrigin::signed(RootAccount::get()), 1),122 Error::<Test>::TooFewInvulnerables123 );124 });125}126127#[test]128fn set_desired_collators_works() {129 new_test_ext().execute_with(|| {130 131 assert_eq!(<DesiredCollators<Test>>::get(), 5);132133 134 assert_ok!(Configuration::set_collator_selection_desired_collators(135 RawOrigin::Root.into(),136 Some(7)137 ));138 assert_eq!(<DesiredCollators<Test>>::get(), 7);139140 141 assert_noop!(142 Configuration::set_collator_selection_desired_collators(143 RuntimeOrigin::signed(1),144 Some(8)145 ),146 BadOrigin147 );148 });149}150151#[test]152fn set_license_bond() {153 new_test_ext().execute_with(|| {154 155 assert_eq!(<LicenseBond<Test>>::get(), 10);156157 158 assert_ok!(Configuration::set_collator_selection_license_bond(159 RawOrigin::Root.into(),160 Some(7)161 ));162 assert_eq!(<LicenseBond<Test>>::get(), 7);163164 165 assert_noop!(166 Configuration::set_collator_selection_license_bond(RuntimeOrigin::signed(1), Some(8)),167 BadOrigin168 );169 });170}171172#[test]173fn cannot_onboard_candidate_with_no_license() {174 new_test_ext().execute_with(|| {175 176 assert_noop!(177 CollatorSelection::onboard(RuntimeOrigin::signed(3)),178 Error::<Test>::NoLicense,179 );180181 182 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(3)));183 assert_ok!(CollatorSelection::onboard(RuntimeOrigin::signed(3)));184 })185}186187#[test]188fn cannot_onboard_candidate_if_too_many() {189 new_test_ext().execute_with(|| {190 191 <pallet_configuration::CollatorSelectionDesiredCollatorsOverride<Test>>::put(0);192193 194 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(4)));195196 197 assert_noop!(198 CollatorSelection::onboard(RuntimeOrigin::signed(4)),199 Error::<Test>::TooManyCandidates,200 );201202 203 <pallet_configuration::CollatorSelectionDesiredCollatorsOverride<Test>>::put(3);204 assert_ok!(CollatorSelection::onboard(RuntimeOrigin::signed(4)));205206 207 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(5)));208 assert_noop!(209 CollatorSelection::onboard(RuntimeOrigin::signed(5)),210 Error::<Test>::TooManyCandidates,211 );212 })213}214215#[test]216fn cannot_obtain_license_if_keys_not_registered() {217 new_test_ext().execute_with(|| {218 219 assert_noop!(220 CollatorSelection::get_license(RuntimeOrigin::signed(7)),221 Error::<Test>::ValidatorNotRegistered222 );223 })224}225226#[test]227fn cannot_obtain_license_if_poor() {228 new_test_ext().execute_with(|| {229 assert_eq!(Balances::free_balance(&3), 100);230 assert_eq!(Balances::free_balance(&33), 0);231232 233 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(3)));234235 236 assert_noop!(237 CollatorSelection::get_license(RuntimeOrigin::signed(33)),238 BalancesError::<Test>::InsufficientBalance,239 );240 });241}242243#[test]244fn cannot_onboard_dupe_candidate() {245 new_test_ext().execute_with(|| {246 247 get_license_and_onboard(3);248 assert_eq!(CollatorSelection::license_deposit_of(3), 10);249 assert_eq!(CollatorSelection::candidates(), vec![3]);250 assert_eq!(CollatorSelection::last_authored_block(3), 10);251 assert_eq!(Balances::free_balance(3), 90);252253 254 assert_noop!(255 CollatorSelection::get_license(RuntimeOrigin::signed(3)),256 Error::<Test>::AlreadyHoldingLicense,257 );258 assert_noop!(259 CollatorSelection::onboard(RuntimeOrigin::signed(3)),260 Error::<Test>::AlreadyCandidate,261 );262 })263}264265#[test]266fn becoming_candidate_works() {267 new_test_ext().execute_with(|| {268 269 assert_eq!(<DesiredCollators<Test>>::get(), 5);270 assert_eq!(<LicenseBond<Test>>::get(), 10);271 assert_eq!(CollatorSelection::candidates(), Vec::new());272 assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);273274 275 assert_eq!(Balances::free_balance(&3), 100);276 assert_eq!(Balances::free_balance(&4), 100);277278 get_license_and_onboard(3);279 get_license_and_onboard(4);280281 assert_eq!(Balances::free_balance(&3), 90);282 assert_eq!(Balances::free_balance(&4), 90);283284 assert_eq!(CollatorSelection::candidates().len(), 2);285 });286}287288#[test]289fn cannot_become_candidate_if_invulnerable() {290 new_test_ext().execute_with(|| {291 assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);292293 294 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(1)));295 296 assert_noop!(297 CollatorSelection::onboard(RuntimeOrigin::signed(1)),298 Error::<Test>::AlreadyInvulnerable,299 );300301 302 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(3)));303 assert_ok!(CollatorSelection::add_invulnerable(304 RuntimeOrigin::signed(RootAccount::get()),305 3306 ));307 assert_noop!(308 CollatorSelection::onboard(RuntimeOrigin::signed(3)),309 Error::<Test>::AlreadyInvulnerable,310 );311 })312}313314#[test]315fn can_become_invulnerable_if_candidate() {316 new_test_ext().execute_with(|| {317 318 get_license_and_onboard(3);319 assert_eq!(CollatorSelection::candidates(), vec![3]);320321 assert_ok!(CollatorSelection::add_invulnerable(322 RuntimeOrigin::signed(RootAccount::get()),323 3324 ));325 326 assert_eq!(CollatorSelection::candidates(), vec![]);327 assert_eq!(CollatorSelection::license_deposit_of(3), 10);328 assert_eq!(Balances::free_balance(3), 90);329 });330}331332#[test]333fn offboard() {334 new_test_ext().execute_with(|| {335 336 get_license_and_onboard(3);337 assert_eq!(Balances::free_balance(3), 90);338339 340 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(4)));341 assert_noop!(342 CollatorSelection::offboard(RuntimeOrigin::signed(4)),343 Error::<Test>::NotCandidate344 );345 346 assert_noop!(347 CollatorSelection::offboard(RuntimeOrigin::signed(5)),348 Error::<Test>::NotCandidate349 );350351 352 assert_ok!(CollatorSelection::offboard(RuntimeOrigin::signed(3)));353 assert_eq!(Balances::free_balance(3), 90);354 assert_eq!(CollatorSelection::last_authored_block(3), 0);355 assert_ok!(CollatorSelection::release_license(RuntimeOrigin::signed(3)));356 assert_eq!(Balances::free_balance(3), 100);357 });358}359360#[test]361fn release_license() {362 new_test_ext().execute_with(|| {363 364 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(3)));365 assert_eq!(Balances::free_balance(3), 90);366367 368 assert_ok!(CollatorSelection::release_license(RuntimeOrigin::signed(3)));369 assert_eq!(Balances::free_balance(3), 100);370371 372 get_license_and_onboard(3);373 assert_eq!(Balances::free_balance(3), 90);374375 376 assert_ok!(CollatorSelection::release_license(RuntimeOrigin::signed(3)));377 assert_eq!(Balances::free_balance(3), 100);378 assert_eq!(CollatorSelection::candidates(), vec![]);379 });380}381382#[test]383fn force_release_license() {384 new_test_ext().execute_with(|| {385 386 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(3)));387 assert_eq!(Balances::free_balance(3), 90);388389 390 assert_noop!(391 CollatorSelection::force_release_license(RuntimeOrigin::signed(3), 3),392 BadOrigin393 );394395 396 assert_ok!(CollatorSelection::force_release_license(397 RuntimeOrigin::signed(RootAccount::get()),398 3399 ));400 assert_eq!(Balances::free_balance(3), 100);401402 403 get_license_and_onboard(3);404 assert_eq!(Balances::free_balance(3), 90);405406 407 assert_ok!(CollatorSelection::force_release_license(408 RuntimeOrigin::signed(RootAccount::get()),409 3410 ));411 assert_eq!(Balances::free_balance(3), 100);412 assert_eq!(CollatorSelection::candidates(), vec![]);413 });414}415416#[test]417fn authorship_event_handler() {418 new_test_ext().execute_with(|| {419 420 <pallet_balances::Pallet<T> as fungible::Mutate<T::AccountId>>::set_balance(421 &CollatorSelection::account_id(),422 105,423 );424425 426 assert_eq!(Balances::free_balance(4), 100);427 get_license_and_onboard(4);428 429 Authorship::on_initialize(1);430431 assert_eq!(CollatorSelection::candidates(), vec![4]);432 assert_eq!(CollatorSelection::last_authored_block(4), 0);433434 435 assert_eq!(Balances::free_balance(4), 140);436 437 assert_eq!(Balances::free_balance(CollatorSelection::account_id()), 55);438 });439}440441#[test]442fn fees_edgecases() {443 new_test_ext().execute_with(|| {444 445 Authorship::on_initialize(1);446 447 <pallet_balances::Pallet<T> as fungible::Mutate<T::AccountId>>::set_balance(448 &CollatorSelection::account_id(),449 5,450 );451 452 assert_eq!(Balances::free_balance(4), 100);453 get_license_and_onboard(4);454 455 Authorship::on_initialize(1);456457 assert_eq!(CollatorSelection::candidates(), vec![4]);458 assert_eq!(CollatorSelection::last_authored_block(4), 0);459 460 assert_eq!(Balances::free_balance(4), 90);461 462 assert_eq!(Balances::free_balance(CollatorSelection::account_id()), 5);463 });464}465466#[test]467fn session_management_works() {468 new_test_ext().execute_with(|| {469 initialize_to_block(1);470471 assert_eq!(SessionChangeBlock::get(), 0);472 assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);473474 initialize_to_block(4);475476 assert_eq!(SessionChangeBlock::get(), 0);477 assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);478479 480 get_license_and_onboard(5);481482 483 assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);484 485 assert_eq!(CollatorSelection::candidates().len(), 1);486487 initialize_to_block(10);488 assert_eq!(SessionChangeBlock::get(), 10);489 490 assert_eq!(Session::validators(), vec![1, 2]);491 492 assert_eq!(Session::queued_keys().len(), 3);493 494 assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);495496 initialize_to_block(20);497 assert_eq!(SessionChangeBlock::get(), 20);498 499 assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 5]);500 });501}502503#[test]504fn kick_mechanism() {505 new_test_ext().execute_with(|| {506 507 get_license_and_onboard(3);508 get_license_and_onboard(4);509510 initialize_to_block(10);511 assert_eq!(CollatorSelection::candidates().len(), 2);512513 initialize_to_block(20);514 assert_eq!(SessionChangeBlock::get(), 20);515 516 assert_eq!(CollatorSelection::candidates().len(), 1);517 518 assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 3, 4]);519520 assert_eq!(CollatorSelection::candidates(), vec![4]);521 assert_eq!(<KickThreshold<Test>>::get(), 10);522 assert_eq!(CollatorSelection::last_authored_block(4), 20);523524 initialize_to_block(30);525 526 assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 4]);527 528 assert_eq!(Balances::free_balance(3), 90);529 });530}531532#[test]533#[should_panic = "duplicate invulnerables in genesis."]534fn cannot_set_genesis_value_twice() {535 sp_tracing::try_init_simple();536 let mut t = frame_system::GenesisConfig::default()537 .build_storage::<Test>()538 .unwrap();539 let invulnerables = vec![1, 1];540541 let collator_selection = collator_selection::GenesisConfig::<Test> { invulnerables };542 543 collator_selection.assimilate_storage(&mut t).unwrap();544}