123456789101112131415161718192021222324252627282930313233use crate as collator_selection;34use crate::{mock::*, Error};35use frame_support::{36 assert_noop, assert_ok,37 traits::{fungible, GenesisBuild, OnInitialize},38};39use frame_system::RawOrigin;40use sp_runtime::{traits::BadOrigin, TokenError};41use pallet_configuration::{42 CollatorSelectionDesiredCollatorsOverride as DesiredCollators,43 CollatorSelectionKickThresholdOverride as KickThreshold,44 CollatorSelectionLicenseBondOverride as LicenseBond,45};46use scale_info::prelude::*;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 let ed = <Test as pallet_balances::Config>::ExistentialDeposit::get();230 assert_eq!(Balances::free_balance(&3), 100);231 assert_eq!(Balances::free_balance(&33), ed);232233 234 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(3)));235236 237 assert_noop!(238 CollatorSelection::get_license(RuntimeOrigin::signed(33)),239 TokenError::FundsUnavailable,240 );241 });242}243244#[test]245fn cannot_onboard_dupe_candidate() {246 new_test_ext().execute_with(|| {247 248 get_license_and_onboard(3);249 assert_eq!(CollatorSelection::license_deposit_of(3), 10);250 assert_eq!(CollatorSelection::candidates(), vec![3]);251 assert_eq!(CollatorSelection::last_authored_block(3), 10);252 assert_eq!(Balances::free_balance(3), 90);253254 255 assert_noop!(256 CollatorSelection::get_license(RuntimeOrigin::signed(3)),257 Error::<Test>::AlreadyHoldingLicense,258 );259 assert_noop!(260 CollatorSelection::onboard(RuntimeOrigin::signed(3)),261 Error::<Test>::AlreadyCandidate,262 );263 })264}265266#[test]267fn becoming_candidate_works() {268 new_test_ext().execute_with(|| {269 270 assert_eq!(<DesiredCollators<Test>>::get(), 5);271 assert_eq!(<LicenseBond<Test>>::get(), 10);272 assert_eq!(CollatorSelection::candidates(), Vec::new());273 assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);274275 276 assert_eq!(Balances::free_balance(&3), 100);277 assert_eq!(Balances::free_balance(&4), 100);278279 get_license_and_onboard(3);280 get_license_and_onboard(4);281282 assert_eq!(Balances::free_balance(&3), 90);283 assert_eq!(Balances::free_balance(&4), 90);284285 assert_eq!(CollatorSelection::candidates().len(), 2);286 });287}288289#[test]290fn cannot_become_candidate_if_invulnerable() {291 new_test_ext().execute_with(|| {292 assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);293294 295 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(1)));296 297 assert_noop!(298 CollatorSelection::onboard(RuntimeOrigin::signed(1)),299 Error::<Test>::AlreadyInvulnerable,300 );301302 303 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(3)));304 assert_ok!(CollatorSelection::add_invulnerable(305 RuntimeOrigin::signed(RootAccount::get()),306 3307 ));308 assert_noop!(309 CollatorSelection::onboard(RuntimeOrigin::signed(3)),310 Error::<Test>::AlreadyInvulnerable,311 );312 })313}314315#[test]316fn can_become_invulnerable_if_candidate() {317 new_test_ext().execute_with(|| {318 319 get_license_and_onboard(3);320 assert_eq!(CollatorSelection::candidates(), vec![3]);321322 assert_ok!(CollatorSelection::add_invulnerable(323 RuntimeOrigin::signed(RootAccount::get()),324 3325 ));326 327 assert_eq!(CollatorSelection::candidates(), vec![]);328 assert_eq!(CollatorSelection::license_deposit_of(3), 10);329 assert_eq!(Balances::free_balance(3), 90);330 });331}332333#[test]334fn offboard() {335 new_test_ext().execute_with(|| {336 337 get_license_and_onboard(3);338 assert_eq!(Balances::free_balance(3), 90);339340 341 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(4)));342 assert_noop!(343 CollatorSelection::offboard(RuntimeOrigin::signed(4)),344 Error::<Test>::NotCandidate345 );346 347 assert_noop!(348 CollatorSelection::offboard(RuntimeOrigin::signed(5)),349 Error::<Test>::NotCandidate350 );351352 353 assert_ok!(CollatorSelection::offboard(RuntimeOrigin::signed(3)));354 assert_eq!(Balances::free_balance(3), 90);355 assert_eq!(CollatorSelection::last_authored_block(3), 0);356 assert_ok!(CollatorSelection::release_license(RuntimeOrigin::signed(3)));357 assert_eq!(Balances::free_balance(3), 100);358 });359}360361#[test]362fn release_license() {363 new_test_ext().execute_with(|| {364 365 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(3)));366 assert_eq!(Balances::free_balance(3), 90);367368 369 assert_ok!(CollatorSelection::release_license(RuntimeOrigin::signed(3)));370 assert_eq!(Balances::free_balance(3), 100);371372 373 get_license_and_onboard(3);374 assert_eq!(Balances::free_balance(3), 90);375376 377 assert_ok!(CollatorSelection::release_license(RuntimeOrigin::signed(3)));378 assert_eq!(Balances::free_balance(3), 100);379 assert_eq!(CollatorSelection::candidates(), vec![]);380 });381}382383#[test]384fn force_release_license() {385 new_test_ext().execute_with(|| {386 387 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(3)));388 assert_eq!(Balances::free_balance(3), 90);389390 391 assert_noop!(392 CollatorSelection::force_release_license(RuntimeOrigin::signed(3), 3),393 BadOrigin394 );395396 397 assert_ok!(CollatorSelection::force_release_license(398 RuntimeOrigin::signed(RootAccount::get()),399 3400 ));401 assert_eq!(Balances::free_balance(3), 100);402403 404 get_license_and_onboard(3);405 assert_eq!(Balances::free_balance(3), 90);406407 408 assert_ok!(CollatorSelection::force_release_license(409 RuntimeOrigin::signed(RootAccount::get()),410 3411 ));412 assert_eq!(Balances::free_balance(3), 100);413 assert_eq!(CollatorSelection::candidates(), vec![]);414 });415}416417#[test]418fn authorship_event_handler() {419 new_test_ext().execute_with(|| {420 421 <Balances as fungible::Mutate<_>>::set_balance(&CollatorSelection::account_id(), 105);422423 424 assert_eq!(Balances::free_balance(4), 100);425 get_license_and_onboard(4);426 427 Authorship::on_initialize(1);428429 assert_eq!(CollatorSelection::candidates(), vec![4]);430 assert_eq!(CollatorSelection::last_authored_block(4), 0);431432 433 assert_eq!(Balances::free_balance(4), 140);434 435 assert_eq!(Balances::free_balance(CollatorSelection::account_id()), 55);436 });437}438439#[test]440fn fees_edgecases() {441 new_test_ext().execute_with(|| {442 443 Authorship::on_initialize(1);444 445 <Balances as fungible::Mutate<_>>::set_balance(&CollatorSelection::account_id(), 5);446 447 assert_eq!(Balances::free_balance(4), 100);448 get_license_and_onboard(4);449 450 Authorship::on_initialize(1);451452 assert_eq!(CollatorSelection::candidates(), vec![4]);453 assert_eq!(CollatorSelection::last_authored_block(4), 0);454 455 assert_eq!(Balances::free_balance(4), 90);456 457 assert_eq!(Balances::free_balance(CollatorSelection::account_id()), 5);458 });459}460461#[test]462fn session_management_works() {463 new_test_ext().execute_with(|| {464 initialize_to_block(1);465466 assert_eq!(SessionChangeBlock::get(), 0);467 assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);468469 initialize_to_block(4);470471 assert_eq!(SessionChangeBlock::get(), 0);472 assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);473474 475 get_license_and_onboard(5);476477 478 assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);479 480 assert_eq!(CollatorSelection::candidates().len(), 1);481482 initialize_to_block(10);483 assert_eq!(SessionChangeBlock::get(), 10);484 485 assert_eq!(Session::validators(), vec![1, 2]);486 487 assert_eq!(Session::queued_keys().len(), 3);488 489 assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);490491 initialize_to_block(20);492 assert_eq!(SessionChangeBlock::get(), 20);493 494 assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 5]);495 });496}497498#[test]499fn kick_mechanism() {500 new_test_ext().execute_with(|| {501 502 get_license_and_onboard(3);503 get_license_and_onboard(4);504505 initialize_to_block(10);506 assert_eq!(CollatorSelection::candidates().len(), 2);507508 initialize_to_block(20);509 assert_eq!(SessionChangeBlock::get(), 20);510 511 assert_eq!(CollatorSelection::candidates().len(), 1);512 513 assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 3, 4]);514515 assert_eq!(CollatorSelection::candidates(), vec![4]);516 assert_eq!(<KickThreshold<Test>>::get(), 10);517 assert_eq!(CollatorSelection::last_authored_block(4), 20);518519 initialize_to_block(30);520 521 assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 4]);522 523 assert_eq!(Balances::free_balance(3), 90);524 });525}526527#[test]528#[should_panic = "duplicate invulnerables in genesis."]529fn cannot_set_genesis_value_twice() {530 sp_tracing::try_init_simple();531 let mut t = frame_system::GenesisConfig::default()532 .build_storage::<Test>()533 .unwrap();534 let invulnerables = vec![1, 1];535536 let collator_selection = collator_selection::GenesisConfig::<Test> { invulnerables };537 538 collator_selection.assimilate_storage(&mut t).unwrap();539}