123456789101112131415161718192021222324252627282930313233use crate as collator_selection;34use crate::{mock::*, Error};35use frame_support::{36 assert_noop, assert_ok,37 traits::{Currency, GenesisBuild, OnInitialize},38};39use pallet_balances::Error as BalancesError;40use sp_runtime::traits::BadOrigin;4142fn get_license_and_onboard(account_id: <Test as frame_system::Config>::AccountId) {43 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(44 account_id45 )));46 assert_ok!(CollatorSelection::onboard(RuntimeOrigin::signed(47 account_id48 )));49}5051#[test]52fn basic_setup_works() {53 new_test_ext().execute_with(|| {54 assert_eq!(CollatorSelection::desired_collators(), 5);55 assert_eq!(CollatorSelection::license_bond(), 10);5657 assert!(CollatorSelection::candidates().is_empty());58 assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);59 });60}6162636465#[test]66fn it_should_add_invulnerables() {67 new_test_ext().execute_with(|| {68 assert_ok!(CollatorSelection::add_invulnerable(69 RuntimeOrigin::signed(RootAccount::get()),70 171 ));72 assert_ok!(CollatorSelection::add_invulnerable(73 RuntimeOrigin::signed(RootAccount::get()),74 275 ));76 assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);7778 79 assert_noop!(80 CollatorSelection::add_invulnerable(RuntimeOrigin::signed(1), 3),81 BadOrigin82 );8384 85 assert_noop!(86 CollatorSelection::add_invulnerable(RuntimeOrigin::signed(RootAccount::get()), 7),87 Error::<Test>::ValidatorNotRegistered88 );89 });90}9192#[test]93fn it_should_remove_invulnerables() {94 new_test_ext().execute_with(|| {95 assert_ok!(CollatorSelection::add_invulnerable(96 RuntimeOrigin::signed(RootAccount::get()),97 198 ));99 assert_ok!(CollatorSelection::add_invulnerable(100 RuntimeOrigin::signed(RootAccount::get()),101 2102 ));103104 105 assert_noop!(106 CollatorSelection::remove_invulnerable(RuntimeOrigin::signed(1), 3),107 BadOrigin108 );109110 assert_ok!(CollatorSelection::remove_invulnerable(111 RuntimeOrigin::signed(RootAccount::get()),112 2113 ));114 assert_eq!(CollatorSelection::invulnerables(), vec![1]);115116 117 assert_noop!(118 CollatorSelection::remove_invulnerable(RuntimeOrigin::signed(RootAccount::get()), 1),119 Error::<Test>::TooFewInvulnerables120 );121 });122}123124#[test]125fn set_desired_collators_works() {126 new_test_ext().execute_with(|| {127 128 assert_eq!(CollatorSelection::desired_collators(), 5);129130 131 assert_ok!(CollatorSelection::set_desired_collators(132 RuntimeOrigin::signed(RootAccount::get()),133 7134 ));135 assert_eq!(CollatorSelection::desired_collators(), 7);136137 138 assert_noop!(139 CollatorSelection::set_desired_collators(RuntimeOrigin::signed(1), 8),140 BadOrigin141 );142 });143}144145#[test]146fn set_license_bond() {147 new_test_ext().execute_with(|| {148 149 assert_eq!(CollatorSelection::license_bond(), 10);150151 152 assert_ok!(CollatorSelection::set_license_bond(153 RuntimeOrigin::signed(RootAccount::get()),154 7155 ));156 assert_eq!(CollatorSelection::license_bond(), 7);157158 159 assert_noop!(160 CollatorSelection::set_license_bond(RuntimeOrigin::signed(1), 8),161 BadOrigin162 );163 });164}165166#[test]167fn cannot_onboard_candidate_with_no_license() {168 new_test_ext().execute_with(|| {169 170 assert_noop!(171 CollatorSelection::onboard(RuntimeOrigin::signed(3)),172 Error::<Test>::NoLicense,173 );174175 176 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(3)));177 assert_ok!(CollatorSelection::onboard(RuntimeOrigin::signed(3)));178 })179}180181#[test]182fn cannot_onboard_candidate_if_too_many() {183 new_test_ext().execute_with(|| {184 185 <crate::DesiredCollators<Test>>::put(0);186187 188 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(4)));189190 191 assert_noop!(192 CollatorSelection::onboard(RuntimeOrigin::signed(4)),193 Error::<Test>::TooManyCandidates,194 );195196 197 <crate::DesiredCollators<Test>>::put(3);198 assert_ok!(CollatorSelection::onboard(RuntimeOrigin::signed(4)));199200 201 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(5)));202 assert_noop!(203 CollatorSelection::onboard(RuntimeOrigin::signed(5)),204 Error::<Test>::TooManyCandidates,205 );206 })207}208209#[test]210fn cannot_obtain_license_if_keys_not_registered() {211 new_test_ext().execute_with(|| {212 213 assert_noop!(214 CollatorSelection::get_license(RuntimeOrigin::signed(7)),215 Error::<Test>::ValidatorNotRegistered216 );217 })218}219220#[test]221fn cannot_obtain_license_if_poor() {222 new_test_ext().execute_with(|| {223 assert_eq!(Balances::free_balance(&3), 100);224 assert_eq!(Balances::free_balance(&33), 0);225226 227 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(3)));228229 230 assert_noop!(231 CollatorSelection::get_license(RuntimeOrigin::signed(33)),232 BalancesError::<Test>::InsufficientBalance,233 );234 });235}236237#[test]238fn cannot_onboard_dupe_candidate() {239 new_test_ext().execute_with(|| {240 241 get_license_and_onboard(3);242 assert_eq!(CollatorSelection::licenses(3), 10);243 assert_eq!(CollatorSelection::candidates(), vec![3]);244 assert_eq!(CollatorSelection::last_authored_block(3), 10);245 assert_eq!(Balances::free_balance(3), 90);246247 248 assert_noop!(249 CollatorSelection::get_license(RuntimeOrigin::signed(3)),250 Error::<Test>::AlreadyHoldingLicense,251 );252 assert_noop!(253 CollatorSelection::onboard(RuntimeOrigin::signed(3)),254 Error::<Test>::AlreadyCandidate,255 );256 })257}258259#[test]260fn becoming_candidate_works() {261 new_test_ext().execute_with(|| {262 263 assert_eq!(CollatorSelection::desired_collators(), 5);264 assert_eq!(CollatorSelection::license_bond(), 10);265 assert_eq!(CollatorSelection::candidates(), Vec::new());266 assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);267268 269 assert_eq!(Balances::free_balance(&3), 100);270 assert_eq!(Balances::free_balance(&4), 100);271272 get_license_and_onboard(3);273 get_license_and_onboard(4);274275 assert_eq!(Balances::free_balance(&3), 90);276 assert_eq!(Balances::free_balance(&4), 90);277278 assert_eq!(CollatorSelection::candidates().len(), 2);279 });280}281282#[test]283fn cannot_become_candidate_if_invulnerable() {284 new_test_ext().execute_with(|| {285 assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);286287 288 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(1)));289 290 assert_noop!(291 CollatorSelection::onboard(RuntimeOrigin::signed(1)),292 Error::<Test>::AlreadyInvulnerable,293 );294295 296 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(3)));297 assert_ok!(CollatorSelection::add_invulnerable(298 RuntimeOrigin::signed(RootAccount::get()),299 3300 ));301 assert_noop!(302 CollatorSelection::onboard(RuntimeOrigin::signed(3)),303 Error::<Test>::AlreadyInvulnerable,304 );305 })306}307308#[test]309fn can_become_invulnerable_if_candidate() {310 new_test_ext().execute_with(|| {311 312 get_license_and_onboard(3);313 assert_eq!(CollatorSelection::candidates(), vec![3]);314315 assert_ok!(CollatorSelection::add_invulnerable(316 RuntimeOrigin::signed(RootAccount::get()),317 3318 ));319 320 assert_eq!(CollatorSelection::candidates(), vec![]);321 assert_eq!(CollatorSelection::licenses(3), 10);322 assert_eq!(Balances::free_balance(3), 90);323 });324}325326#[test]327fn offboard() {328 new_test_ext().execute_with(|| {329 330 get_license_and_onboard(3);331 assert_eq!(Balances::free_balance(3), 90);332333 334 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(4)));335 assert_noop!(336 CollatorSelection::offboard(RuntimeOrigin::signed(4)),337 Error::<Test>::NotCandidate338 );339 340 assert_noop!(341 CollatorSelection::offboard(RuntimeOrigin::signed(5)),342 Error::<Test>::NotCandidate343 );344345 346 assert_ok!(CollatorSelection::offboard(RuntimeOrigin::signed(3)));347 assert_eq!(Balances::free_balance(3), 90);348 assert_eq!(CollatorSelection::last_authored_block(3), 0);349 assert_ok!(CollatorSelection::release_license(RuntimeOrigin::signed(3)));350 assert_eq!(Balances::free_balance(3), 100);351 });352}353354#[test]355fn release_license() {356 new_test_ext().execute_with(|| {357 358 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(3)));359 assert_eq!(Balances::free_balance(3), 90);360361 362 assert_ok!(CollatorSelection::release_license(RuntimeOrigin::signed(3)));363 assert_eq!(Balances::free_balance(3), 100);364365 366 get_license_and_onboard(3);367 assert_eq!(Balances::free_balance(3), 90);368369 370 assert_ok!(CollatorSelection::release_license(RuntimeOrigin::signed(3)));371 assert_eq!(Balances::free_balance(3), 100);372 assert_eq!(CollatorSelection::candidates(), vec![]);373 });374}375376#[test]377fn force_revoke_license() {378 new_test_ext().execute_with(|| {379 380 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(3)));381 assert_eq!(Balances::free_balance(3), 90);382383 384 assert_noop!(385 CollatorSelection::force_revoke_license(RuntimeOrigin::signed(3), 3),386 BadOrigin387 );388389 390 assert_ok!(CollatorSelection::force_revoke_license(391 RuntimeOrigin::signed(RootAccount::get()),392 3393 ));394 assert_eq!(Balances::free_balance(3), 100);395396 397 get_license_and_onboard(3);398 assert_eq!(Balances::free_balance(3), 90);399400 401 assert_ok!(CollatorSelection::force_revoke_license(402 RuntimeOrigin::signed(RootAccount::get()),403 3404 ));405 assert_eq!(Balances::free_balance(3), 100);406 assert_eq!(CollatorSelection::candidates(), vec![]);407 });408}409410#[test]411fn authorship_event_handler() {412 new_test_ext().execute_with(|| {413 414 Balances::make_free_balance_be(&CollatorSelection::account_id(), 105);415416 417 assert_eq!(Balances::free_balance(4), 100);418 get_license_and_onboard(4);419 420 Authorship::on_initialize(1);421422 assert_eq!(CollatorSelection::candidates(), vec![4]);423 assert_eq!(CollatorSelection::last_authored_block(4), 0);424425 426 assert_eq!(Balances::free_balance(4), 140);427 428 assert_eq!(Balances::free_balance(CollatorSelection::account_id()), 55);429 });430}431432#[test]433fn fees_edgecases() {434 new_test_ext().execute_with(|| {435 436 Authorship::on_initialize(1);437 438 Balances::make_free_balance_be(&CollatorSelection::account_id(), 5);439 440 assert_eq!(Balances::free_balance(4), 100);441 get_license_and_onboard(4);442 443 Authorship::on_initialize(1);444445 assert_eq!(CollatorSelection::candidates(), vec![4]);446 assert_eq!(CollatorSelection::last_authored_block(4), 0);447 448 assert_eq!(Balances::free_balance(4), 90);449 450 assert_eq!(Balances::free_balance(CollatorSelection::account_id()), 5);451 });452}453454#[test]455fn session_management_works() {456 new_test_ext().execute_with(|| {457 initialize_to_block(1);458459 assert_eq!(SessionChangeBlock::get(), 0);460 assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);461462 initialize_to_block(4);463464 assert_eq!(SessionChangeBlock::get(), 0);465 assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);466467 468 get_license_and_onboard(5);469470 471 assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);472 473 assert_eq!(CollatorSelection::candidates().len(), 1);474475 initialize_to_block(10);476 assert_eq!(SessionChangeBlock::get(), 10);477 478 assert_eq!(Session::validators(), vec![1, 2]);479 480 assert_eq!(Session::queued_keys().len(), 3);481 482 assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);483484 initialize_to_block(20);485 assert_eq!(SessionChangeBlock::get(), 20);486 487 assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 5]);488 });489}490491#[test]492fn kick_mechanism() {493 new_test_ext().execute_with(|| {494 495 get_license_and_onboard(3);496 get_license_and_onboard(4);497498 initialize_to_block(10);499 assert_eq!(CollatorSelection::candidates().len(), 2);500501 initialize_to_block(20);502 assert_eq!(SessionChangeBlock::get(), 20);503 504 assert_eq!(CollatorSelection::candidates().len(), 1);505 506 assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 3, 4]);507508 assert_eq!(CollatorSelection::candidates(), vec![4]);509 assert_eq!(CollatorSelection::kick_threshold(), 10);510 assert_eq!(CollatorSelection::last_authored_block(4), 20);511512 initialize_to_block(30);513 514 assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 4]);515 516 assert_eq!(Balances::free_balance(3), 90);517 });518}519520#[test]521#[should_panic = "duplicate invulnerables in genesis."]522fn cannot_set_genesis_value_twice() {523 sp_tracing::try_init_simple();524 let mut t = frame_system::GenesisConfig::default()525 .build_storage::<Test>()526 .unwrap();527 let invulnerables = vec![1, 1];528529 let collator_selection = collator_selection::GenesisConfig::<Test> {530 desired_collators: 5,531 license_bond: 10,532 kick_threshold: 10,533 invulnerables,534 };535 536 collator_selection.assimilate_storage(&mut t).unwrap();537}