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}6162#[test]63fn it_should_add_invulnerables() {64 new_test_ext().execute_with(|| {65 assert_ok!(CollatorSelection::add_invulnerable(66 RuntimeOrigin::signed(RootAccount::get()),67 168 ));69 assert_ok!(CollatorSelection::add_invulnerable(70 RuntimeOrigin::signed(RootAccount::get()),71 272 ));73 assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);7475 76 assert_noop!(77 CollatorSelection::add_invulnerable(RuntimeOrigin::signed(1), 3),78 BadOrigin79 );8081 82 assert_noop!(83 CollatorSelection::add_invulnerable(RuntimeOrigin::signed(RootAccount::get()), 7),84 Error::<Test>::ValidatorNotRegistered85 );86 });87}8889#[test]90fn it_should_remove_invulnerables() {91 new_test_ext().execute_with(|| {92 assert_ok!(CollatorSelection::add_invulnerable(93 RuntimeOrigin::signed(RootAccount::get()),94 195 ));96 assert_ok!(CollatorSelection::add_invulnerable(97 RuntimeOrigin::signed(RootAccount::get()),98 299 ));100101 102 assert_noop!(103 CollatorSelection::remove_invulnerable(RuntimeOrigin::signed(1), 3),104 BadOrigin105 );106107 assert_ok!(CollatorSelection::remove_invulnerable(108 RuntimeOrigin::signed(RootAccount::get()),109 2110 ));111 assert_eq!(CollatorSelection::invulnerables(), vec![1]);112113 114 assert_noop!(115 CollatorSelection::remove_invulnerable(RuntimeOrigin::signed(RootAccount::get()), 1),116 Error::<Test>::TooFewInvulnerables117 );118 });119}120121#[test]122fn set_desired_collators_works() {123 new_test_ext().execute_with(|| {124 125 assert_eq!(CollatorSelection::desired_collators(), 5);126127 128 assert_ok!(CollatorSelection::set_desired_collators(129 RuntimeOrigin::signed(RootAccount::get()),130 7131 ));132 assert_eq!(CollatorSelection::desired_collators(), 7);133134 135 assert_noop!(136 CollatorSelection::set_desired_collators(RuntimeOrigin::signed(1), 8),137 BadOrigin138 );139 });140}141142#[test]143fn set_license_bond() {144 new_test_ext().execute_with(|| {145 146 assert_eq!(CollatorSelection::license_bond(), 10);147148 149 assert_ok!(CollatorSelection::set_license_bond(150 RuntimeOrigin::signed(RootAccount::get()),151 7152 ));153 assert_eq!(CollatorSelection::license_bond(), 7);154155 156 assert_noop!(157 CollatorSelection::set_license_bond(RuntimeOrigin::signed(1), 8),158 BadOrigin159 );160 });161}162163#[test]164fn cannot_onboard_candidate_with_no_license() {165 new_test_ext().execute_with(|| {166 167 assert_noop!(168 CollatorSelection::onboard(RuntimeOrigin::signed(3)),169 Error::<Test>::NoLicense,170 );171172 173 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(3)));174 assert_ok!(CollatorSelection::onboard(RuntimeOrigin::signed(3)));175 })176}177178#[test]179fn cannot_onboard_candidate_if_too_many() {180 new_test_ext().execute_with(|| {181 182 <crate::DesiredCollators<Test>>::put(0);183184 185 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(4)));186187 188 assert_noop!(189 CollatorSelection::onboard(RuntimeOrigin::signed(4)),190 Error::<Test>::TooManyCandidates,191 );192193 194 <crate::DesiredCollators<Test>>::put(3);195 assert_ok!(CollatorSelection::onboard(RuntimeOrigin::signed(4)));196197 198 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(5)));199 assert_noop!(200 CollatorSelection::onboard(RuntimeOrigin::signed(5)),201 Error::<Test>::TooManyCandidates,202 );203 })204}205206#[test]207fn cannot_obtain_license_if_keys_not_registered() {208 new_test_ext().execute_with(|| {209 210 assert_noop!(211 CollatorSelection::get_license(RuntimeOrigin::signed(7)),212 Error::<Test>::ValidatorNotRegistered213 );214 })215}216217#[test]218fn cannot_obtain_license_if_poor() {219 new_test_ext().execute_with(|| {220 assert_eq!(Balances::free_balance(&3), 100);221 assert_eq!(Balances::free_balance(&33), 0);222223 224 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(3)));225226 227 assert_noop!(228 CollatorSelection::get_license(RuntimeOrigin::signed(33)),229 BalancesError::<Test>::InsufficientBalance,230 );231 });232}233234#[test]235fn cannot_onboard_dupe_candidate() {236 new_test_ext().execute_with(|| {237 238 get_license_and_onboard(3);239 assert_eq!(CollatorSelection::licenses(3), 10);240 assert_eq!(CollatorSelection::candidates(), vec![3]);241 assert_eq!(CollatorSelection::last_authored_block(3), 10);242 assert_eq!(Balances::free_balance(3), 90);243244 245 assert_noop!(246 CollatorSelection::get_license(RuntimeOrigin::signed(3)),247 Error::<Test>::AlreadyHoldingLicense,248 );249 assert_noop!(250 CollatorSelection::onboard(RuntimeOrigin::signed(3)),251 Error::<Test>::AlreadyCandidate,252 );253 })254}255256#[test]257fn becoming_candidate_works() {258 new_test_ext().execute_with(|| {259 260 assert_eq!(CollatorSelection::desired_collators(), 5);261 assert_eq!(CollatorSelection::license_bond(), 10);262 assert_eq!(CollatorSelection::candidates(), Vec::new());263 assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);264265 266 assert_eq!(Balances::free_balance(&3), 100);267 assert_eq!(Balances::free_balance(&4), 100);268269 get_license_and_onboard(3);270 get_license_and_onboard(4);271272 assert_eq!(Balances::free_balance(&3), 90);273 assert_eq!(Balances::free_balance(&4), 90);274275 assert_eq!(CollatorSelection::candidates().len(), 2);276 });277}278279#[test]280fn cannot_become_candidate_if_invulnerable() {281 new_test_ext().execute_with(|| {282 assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);283284 285 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(1)));286 287 assert_noop!(288 CollatorSelection::onboard(RuntimeOrigin::signed(1)),289 Error::<Test>::AlreadyInvulnerable,290 );291292 293 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(3)));294 assert_ok!(CollatorSelection::add_invulnerable(295 RuntimeOrigin::signed(RootAccount::get()),296 3297 ));298 assert_noop!(299 CollatorSelection::onboard(RuntimeOrigin::signed(3)),300 Error::<Test>::AlreadyInvulnerable,301 );302 })303}304305#[test]306fn can_become_invulnerable_if_candidate() {307 new_test_ext().execute_with(|| {308 309 get_license_and_onboard(3);310 assert_eq!(CollatorSelection::candidates(), vec![3]);311312 assert_ok!(CollatorSelection::add_invulnerable(313 RuntimeOrigin::signed(RootAccount::get()),314 3315 ));316 317 assert_eq!(CollatorSelection::candidates(), vec![]);318 assert_eq!(CollatorSelection::licenses(3), 10);319 assert_eq!(Balances::free_balance(3), 90);320 });321}322323#[test]324fn offboard() {325 new_test_ext().execute_with(|| {326 327 get_license_and_onboard(3);328 assert_eq!(Balances::free_balance(3), 90);329330 331 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(4)));332 assert_noop!(333 CollatorSelection::offboard(RuntimeOrigin::signed(4)),334 Error::<Test>::NotCandidate335 );336 337 assert_noop!(338 CollatorSelection::offboard(RuntimeOrigin::signed(5)),339 Error::<Test>::NotCandidate340 );341342 343 assert_ok!(CollatorSelection::offboard(RuntimeOrigin::signed(3)));344 assert_eq!(Balances::free_balance(3), 90);345 assert_eq!(CollatorSelection::last_authored_block(3), 0);346 assert_ok!(CollatorSelection::release_license(RuntimeOrigin::signed(3)));347 assert_eq!(Balances::free_balance(3), 100);348 });349}350351#[test]352fn release_license() {353 new_test_ext().execute_with(|| {354 355 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(3)));356 assert_eq!(Balances::free_balance(3), 90);357358 359 assert_ok!(CollatorSelection::release_license(RuntimeOrigin::signed(3)));360 assert_eq!(Balances::free_balance(3), 100);361362 363 get_license_and_onboard(3);364 assert_eq!(Balances::free_balance(3), 90);365366 367 assert_ok!(CollatorSelection::release_license(RuntimeOrigin::signed(3)));368 assert_eq!(Balances::free_balance(3), 100);369 assert_eq!(CollatorSelection::candidates(), vec![]);370 });371}372373#[test]374fn force_revoke_license() {375 new_test_ext().execute_with(|| {376 377 assert_ok!(CollatorSelection::get_license(RuntimeOrigin::signed(3)));378 assert_eq!(Balances::free_balance(3), 90);379380 381 assert_noop!(382 CollatorSelection::force_revoke_license(RuntimeOrigin::signed(3), 3),383 BadOrigin384 );385386 387 assert_ok!(CollatorSelection::force_revoke_license(388 RuntimeOrigin::signed(RootAccount::get()),389 3390 ));391 assert_eq!(Balances::free_balance(3), 100);392393 394 get_license_and_onboard(3);395 assert_eq!(Balances::free_balance(3), 90);396397 398 assert_ok!(CollatorSelection::force_revoke_license(399 RuntimeOrigin::signed(RootAccount::get()),400 3401 ));402 assert_eq!(Balances::free_balance(3), 100);403 assert_eq!(CollatorSelection::candidates(), vec![]);404 });405}406407#[test]408fn authorship_event_handler() {409 new_test_ext().execute_with(|| {410 411 Balances::make_free_balance_be(&CollatorSelection::account_id(), 105);412413 414 assert_eq!(Balances::free_balance(4), 100);415 get_license_and_onboard(4);416 417 Authorship::on_initialize(1);418419 assert_eq!(CollatorSelection::candidates(), vec![4]);420 assert_eq!(CollatorSelection::last_authored_block(4), 0);421422 423 assert_eq!(Balances::free_balance(4), 140);424 425 assert_eq!(Balances::free_balance(CollatorSelection::account_id()), 55);426 });427}428429#[test]430fn fees_edgecases() {431 new_test_ext().execute_with(|| {432 433 Authorship::on_initialize(1);434 435 Balances::make_free_balance_be(&CollatorSelection::account_id(), 5);436 437 assert_eq!(Balances::free_balance(4), 100);438 get_license_and_onboard(4);439 440 Authorship::on_initialize(1);441442 assert_eq!(CollatorSelection::candidates(), vec![4]);443 assert_eq!(CollatorSelection::last_authored_block(4), 0);444 445 assert_eq!(Balances::free_balance(4), 90);446 447 assert_eq!(Balances::free_balance(CollatorSelection::account_id()), 5);448 });449}450451#[test]452fn session_management_works() {453 new_test_ext().execute_with(|| {454 initialize_to_block(1);455456 assert_eq!(SessionChangeBlock::get(), 0);457 assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);458459 initialize_to_block(4);460461 assert_eq!(SessionChangeBlock::get(), 0);462 assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);463464 465 get_license_and_onboard(5);466467 468 assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);469 470 assert_eq!(CollatorSelection::candidates().len(), 1);471472 initialize_to_block(10);473 assert_eq!(SessionChangeBlock::get(), 10);474 475 assert_eq!(Session::validators(), vec![1, 2]);476 477 assert_eq!(Session::queued_keys().len(), 3);478 479 assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);480481 initialize_to_block(20);482 assert_eq!(SessionChangeBlock::get(), 20);483 484 assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 5]);485 });486}487488#[test]489fn kick_mechanism() {490 new_test_ext().execute_with(|| {491 492 get_license_and_onboard(3);493 get_license_and_onboard(4);494495 initialize_to_block(10);496 assert_eq!(CollatorSelection::candidates().len(), 2);497498 initialize_to_block(20);499 assert_eq!(SessionChangeBlock::get(), 20);500 501 assert_eq!(CollatorSelection::candidates().len(), 1);502 503 assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 3, 4]);504505 assert_eq!(CollatorSelection::candidates(), vec![4]);506 assert_eq!(CollatorSelection::kick_threshold(), 10);507 assert_eq!(CollatorSelection::last_authored_block(4), 20);508509 initialize_to_block(30);510 511 assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 4]);512 513 assert_eq!(Balances::free_balance(3), 90);514 });515}516517#[test]518#[should_panic = "duplicate invulnerables in genesis."]519fn cannot_set_genesis_value_twice() {520 sp_tracing::try_init_simple();521 let mut t = frame_system::GenesisConfig::default()522 .build_storage::<Test>()523 .unwrap();524 let invulnerables = vec![1, 1];525526 let collator_selection = collator_selection::GenesisConfig::<Test> {527 desired_collators: 5,528 license_bond: 10,529 kick_threshold: 10,530 invulnerables,531 };532 533 collator_selection.assimilate_storage(&mut t).unwrap();534}