difftreelog
tests(collator-selection): further fixes
in: master
2 files changed
pallets/collator-selection/src/tests.rsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617// Original license:18// Copyright (C) 2021 Parity Technologies (UK) Ltd.19// SPDX-License-Identifier: Apache-2.02021// Licensed under the Apache License, Version 2.0 (the "License");22// you may not use this file except in compliance with the License.23// You may obtain a copy of the License at24//25// http://www.apache.org/licenses/LICENSE-2.026//27// Unless required by applicable law or agreed to in writing, software28// distributed under the License is distributed on an "AS IS" BASIS,29// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.30// See the License for the specific language governing permissions and31// limitations under the License.3233use crate as collator_selection;34use crate::{mock::*, CandidateInfo, 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;4142#[test]43fn basic_setup_works() {44 new_test_ext().execute_with(|| {45 assert_eq!(CollatorSelection::desired_candidates(), 2);46 assert_eq!(CollatorSelection::candidacy_bond(), 10);4748 assert!(CollatorSelection::candidates().is_empty());49 assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);50 });51}5253// todo:collator add more tests later5455#[test]56fn it_should_add_invulnerables() {57 new_test_ext().execute_with(|| {58 assert_ok!(CollatorSelection::add_invulnerable(59 RuntimeOrigin::signed(RootAccount::get()),60 161 ));62 assert_ok!(CollatorSelection::add_invulnerable(63 RuntimeOrigin::signed(RootAccount::get()),64 265 ));66 assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);6768 // cannot set with non-root.69 assert_noop!(70 CollatorSelection::add_invulnerable(RuntimeOrigin::signed(1), 3),71 BadOrigin72 );7374 // cannot set invulnerables without associated validator keys75 assert_noop!(76 CollatorSelection::add_invulnerable(77 RuntimeOrigin::signed(RootAccount::get()),78 779 ),80 Error::<Test>::ValidatorNotRegistered81 );82 });83}8485#[test]86fn it_should_remove_invulnerables() {87 new_test_ext().execute_with(|| {88 assert_ok!(CollatorSelection::add_invulnerable(89 RuntimeOrigin::signed(RootAccount::get()),90 191 ));92 assert_ok!(CollatorSelection::add_invulnerable(93 RuntimeOrigin::signed(RootAccount::get()),94 295 ));9697 // cannot remove with non-root.98 assert_noop!(99 CollatorSelection::remove_invulnerable(RuntimeOrigin::signed(1), 3),100 BadOrigin101 );102103 assert_ok!(CollatorSelection::remove_invulnerable(104 RuntimeOrigin::signed(RootAccount::get()),105 2106 ));107 assert_eq!(CollatorSelection::invulnerables(), vec![1]);108109 // cannot remove an invulnerable if there would be 0 invulnerables.110 assert_noop!(111 CollatorSelection::add_invulnerable(112 RuntimeOrigin::signed(RootAccount::get()), 113 1114 ),115 Error::<Test>::NotInvulnerable116 );117 });118}119120#[test]121fn set_desired_candidates_works() {122 new_test_ext().execute_with(|| {123 // given124 assert_eq!(CollatorSelection::desired_candidates(), 2);125126 // can set127 assert_ok!(CollatorSelection::set_desired_candidates(128 RuntimeOrigin::signed(RootAccount::get()),129 7130 ));131 assert_eq!(CollatorSelection::desired_candidates(), 7);132133 // rejects bad origin134 assert_noop!(135 CollatorSelection::set_desired_candidates(RuntimeOrigin::signed(1), 8),136 BadOrigin137 );138 });139}140141#[test]142fn set_candidacy_bond() {143 new_test_ext().execute_with(|| {144 // given145 assert_eq!(CollatorSelection::candidacy_bond(), 10);146147 // can set148 assert_ok!(CollatorSelection::set_candidacy_bond(149 RuntimeOrigin::signed(RootAccount::get()),150 7151 ));152 assert_eq!(CollatorSelection::candidacy_bond(), 7);153154 // rejects bad origin.155 assert_noop!(156 CollatorSelection::set_candidacy_bond(RuntimeOrigin::signed(1), 8),157 BadOrigin158 );159 });160}161162#[test]163fn cannot_register_candidate_if_too_many() {164 new_test_ext().execute_with(|| {165 // reset desired candidates:166 <crate::DesiredCandidates<Test>>::put(0);167168 // can't accept anyone anymore.169 assert_noop!(170 CollatorSelection::register_as_candidate(RuntimeOrigin::signed(3)),171 Error::<Test>::TooManyCandidates,172 );173174 // reset desired candidates:175 <crate::DesiredCandidates<Test>>::put(1);176 assert_ok!(CollatorSelection::register_as_candidate(177 RuntimeOrigin::signed(4)178 ));179180 // but no more181 assert_noop!(182 CollatorSelection::register_as_candidate(RuntimeOrigin::signed(5)),183 Error::<Test>::TooManyCandidates,184 );185 })186}187188#[test]189fn cannot_unregister_candidate_if_too_few() {190 new_test_ext().execute_with(|| {191 // reset desired candidates:192 <crate::DesiredCandidates<Test>>::put(1);193 assert_ok!(CollatorSelection::register_as_candidate(194 RuntimeOrigin::signed(4)195 ));196197 // can not remove too few198 assert_noop!(199 CollatorSelection::leave_intent(RuntimeOrigin::signed(4)),200 Error::<Test>::TooFewCandidates,201 );202 })203}204205#[test]206fn cannot_register_as_candidate_if_invulnerable() {207 new_test_ext().execute_with(|| {208 assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);209210 // can't 1 because it is invulnerable.211 assert_noop!(212 CollatorSelection::register_as_candidate(RuntimeOrigin::signed(1)),213 Error::<Test>::AlreadyInvulnerable,214 );215 })216}217218#[test]219fn cannot_register_as_candidate_if_keys_not_registered() {220 new_test_ext().execute_with(|| {221 // can't 7 because keys not registered.222 assert_noop!(223 CollatorSelection::register_as_candidate(RuntimeOrigin::signed(7)),224 Error::<Test>::ValidatorNotRegistered225 );226 })227}228229#[test]230fn cannot_register_dupe_candidate() {231 new_test_ext().execute_with(|| {232 // can add 3 as candidate233 assert_ok!(CollatorSelection::register_as_candidate(234 RuntimeOrigin::signed(3)235 ));236 let addition = CandidateInfo {237 who: 3,238 deposit: 10,239 };240 assert_eq!(CollatorSelection::candidates(), vec![addition]);241 assert_eq!(CollatorSelection::last_authored_block(3), 10);242 assert_eq!(Balances::free_balance(3), 90);243244 // but no more245 assert_noop!(246 CollatorSelection::register_as_candidate(RuntimeOrigin::signed(3)),247 Error::<Test>::AlreadyCandidate,248 );249 })250}251252#[test]253fn cannot_register_as_candidate_if_poor() {254 new_test_ext().execute_with(|| {255 assert_eq!(Balances::free_balance(&3), 100);256 assert_eq!(Balances::free_balance(&33), 0);257258 // works259 assert_ok!(CollatorSelection::register_as_candidate(260 RuntimeOrigin::signed(3)261 ));262263 // poor264 assert_noop!(265 CollatorSelection::register_as_candidate(RuntimeOrigin::signed(33)),266 BalancesError::<Test>::InsufficientBalance,267 );268 });269}270271#[test]272fn register_as_candidate_works() {273 new_test_ext().execute_with(|| {274 // given275 assert_eq!(CollatorSelection::desired_candidates(), 2);276 assert_eq!(CollatorSelection::candidacy_bond(), 10);277 assert_eq!(CollatorSelection::candidates(), Vec::new());278 assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);279280 // take two endowed, non-invulnerables accounts.281 assert_eq!(Balances::free_balance(&3), 100);282 assert_eq!(Balances::free_balance(&4), 100);283284 assert_ok!(CollatorSelection::register_as_candidate(285 RuntimeOrigin::signed(3)286 ));287 assert_ok!(CollatorSelection::register_as_candidate(288 RuntimeOrigin::signed(4)289 ));290291 assert_eq!(Balances::free_balance(&3), 90);292 assert_eq!(Balances::free_balance(&4), 90);293294 assert_eq!(CollatorSelection::candidates().len(), 2);295 });296}297298#[test]299fn leave_intent() {300 new_test_ext().execute_with(|| {301 // register a candidate.302 assert_ok!(CollatorSelection::register_as_candidate(303 RuntimeOrigin::signed(3)304 ));305 assert_eq!(Balances::free_balance(3), 90);306307 // register too so can leave above min candidates308 assert_ok!(CollatorSelection::register_as_candidate(309 RuntimeOrigin::signed(5)310 ));311 assert_eq!(Balances::free_balance(5), 90);312313 // cannot leave if not candidate.314 assert_noop!(315 CollatorSelection::leave_intent(RuntimeOrigin::signed(4)),316 Error::<Test>::NotCandidate317 );318319 // bond is returned320 assert_ok!(CollatorSelection::leave_intent(RuntimeOrigin::signed(3)));321 assert_eq!(Balances::free_balance(3), 100);322 assert_eq!(CollatorSelection::last_authored_block(3), 0);323 });324}325326#[test]327fn authorship_event_handler() {328 new_test_ext().execute_with(|| {329 // put 100 in the pot + 5 for ED330 Balances::make_free_balance_be(&CollatorSelection::account_id(), 105);331332 // 4 is the default author.333 assert_eq!(Balances::free_balance(4), 100);334 assert_ok!(CollatorSelection::register_as_candidate(335 RuntimeOrigin::signed(4)336 ));337 // triggers `note_author`338 Authorship::on_initialize(1);339340 let collator = CandidateInfo {341 who: 4,342 deposit: 10,343 };344345 assert_eq!(CollatorSelection::candidates(), vec![collator]);346 assert_eq!(CollatorSelection::last_authored_block(4), 0);347348 // half of the pot goes to the collator who's the author (4 in tests).349 assert_eq!(Balances::free_balance(4), 140);350 // half + ED stays.351 assert_eq!(Balances::free_balance(CollatorSelection::account_id()), 55);352 });353}354355#[test]356fn fees_edgecases() {357 new_test_ext().execute_with(|| {358 // Nothing panics, no reward when no ED in balance359 Authorship::on_initialize(1);360 // put some money into the pot at ED361 Balances::make_free_balance_be(&CollatorSelection::account_id(), 5);362 // 4 is the default author.363 assert_eq!(Balances::free_balance(4), 100);364 assert_ok!(CollatorSelection::register_as_candidate(365 RuntimeOrigin::signed(4)366 ));367 // triggers `note_author`368 Authorship::on_initialize(1);369370 let collator = CandidateInfo {371 who: 4,372 deposit: 10,373 };374375 assert_eq!(CollatorSelection::candidates(), vec![collator]);376 assert_eq!(CollatorSelection::last_authored_block(4), 0);377 // Nothing received378 assert_eq!(Balances::free_balance(4), 90);379 // all fee stays380 assert_eq!(Balances::free_balance(CollatorSelection::account_id()), 5);381 });382}383384#[test]385fn session_management_works() {386 new_test_ext().execute_with(|| {387 initialize_to_block(1);388389 assert_eq!(SessionChangeBlock::get(), 0);390 assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);391392 initialize_to_block(4);393394 assert_eq!(SessionChangeBlock::get(), 0);395 assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);396397 // add a new collator398 assert_ok!(CollatorSelection::register_as_candidate(399 RuntimeOrigin::signed(3)400 ));401402 // session won't see this.403 assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);404 // but we have a new candidate.405 assert_eq!(CollatorSelection::candidates().len(), 1);406407 initialize_to_block(10);408 assert_eq!(SessionChangeBlock::get(), 10);409 // pallet-session has 1 session delay; current validators are the same.410 assert_eq!(Session::validators(), vec![1, 2]);411 // queued ones are changed, and now we have 3.412 assert_eq!(Session::queued_keys().len(), 3);413 // session handlers (aura, et. al.) cannot see this yet.414 assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);415416 initialize_to_block(20);417 assert_eq!(SessionChangeBlock::get(), 20);418 // changed are now reflected to session handlers.419 assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 3]);420 });421}422423#[test]424fn kick_mechanism() {425 new_test_ext().execute_with(|| {426 // add a new collator427 assert_ok!(CollatorSelection::register_as_candidate(428 RuntimeOrigin::signed(3)429 ));430 assert_ok!(CollatorSelection::register_as_candidate(431 RuntimeOrigin::signed(4)432 ));433 initialize_to_block(10);434 assert_eq!(CollatorSelection::candidates().len(), 2);435 initialize_to_block(20);436 assert_eq!(SessionChangeBlock::get(), 20);437 // 4 authored this block, gets to stay 3 was kicked438 assert_eq!(CollatorSelection::candidates().len(), 1);439 // 3 will be kicked after 1 session delay440 assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 3, 4]);441 let collator = CandidateInfo {442 who: 4,443 deposit: 10,444 };445 assert_eq!(CollatorSelection::candidates(), vec![collator]);446 assert_eq!(CollatorSelection::kick_threshold(), 1);447 assert_eq!(CollatorSelection::last_authored_block(4), 20);448 initialize_to_block(30);449 // 3 gets kicked after 1 session delay450 assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 4]);451 // kicked collator gets funds back452 assert_eq!(Balances::free_balance(3), 100);453 });454}455456#[test]457fn should_not_kick_mechanism_too_few() {458 new_test_ext().execute_with(|| {459 // add a new collator460 assert_ok!(CollatorSelection::register_as_candidate(461 RuntimeOrigin::signed(3)462 ));463 assert_ok!(CollatorSelection::register_as_candidate(464 RuntimeOrigin::signed(5)465 ));466 initialize_to_block(10);467 assert_eq!(CollatorSelection::candidates().len(), 2);468 initialize_to_block(20);469 assert_eq!(SessionChangeBlock::get(), 20);470 // 4 authored this block, 5 gets to stay too few 3 was kicked471 assert_eq!(CollatorSelection::candidates().len(), 1);472 // 3 will be kicked after 1 session delay473 assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 3, 5]);474 let collator = CandidateInfo {475 who: 5,476 deposit: 10,477 };478 assert_eq!(CollatorSelection::candidates(), vec![collator]);479 assert_eq!(CollatorSelection::last_authored_block(4), 20);480 initialize_to_block(30);481 // 3 gets kicked after 1 session delay482 assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 5]);483 // kicked collator gets funds back484 assert_eq!(Balances::free_balance(3), 100);485 });486}487488#[test]489#[should_panic = "duplicate invulnerables in genesis."]490fn cannot_set_genesis_value_twice() {491 sp_tracing::try_init_simple();492 let mut t = frame_system::GenesisConfig::default()493 .build_storage::<Test>()494 .unwrap();495 let invulnerables = vec![1, 1];496497 let collator_selection = collator_selection::GenesisConfig::<Test> {498 desired_candidates: 2,499 candidacy_bond: 10,500 kick_threshold: 1,501 invulnerables,502 };503 // collator selection must be initialized before session.504 collator_selection.assimilate_storage(&mut t).unwrap();505}1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617// Original license:18// Copyright (C) 2021 Parity Technologies (UK) Ltd.19// SPDX-License-Identifier: Apache-2.02021// Licensed under the Apache License, Version 2.0 (the "License");22// you may not use this file except in compliance with the License.23// You may obtain a copy of the License at24//25// http://www.apache.org/licenses/LICENSE-2.026//27// Unless required by applicable law or agreed to in writing, software28// distributed under the License is distributed on an "AS IS" BASIS,29// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.30// See the License for the specific language governing permissions and31// limitations under the License.3233use crate as collator_selection;34use crate::{mock::*, CandidateInfo, 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;4142#[test]43fn basic_setup_works() {44 new_test_ext().execute_with(|| {45 assert_eq!(CollatorSelection::desired_candidates(), 2);46 assert_eq!(CollatorSelection::candidacy_bond(), 10);4748 assert!(CollatorSelection::candidates().is_empty());49 assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);50 });51}5253// todo:collator add more tests later5455#[test]56fn it_should_add_invulnerables() {57 new_test_ext().execute_with(|| {58 assert_ok!(CollatorSelection::add_invulnerable(59 RuntimeOrigin::signed(RootAccount::get()),60 161 ));62 assert_ok!(CollatorSelection::add_invulnerable(63 RuntimeOrigin::signed(RootAccount::get()),64 265 ));66 assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);6768 // cannot set with non-root.69 assert_noop!(70 CollatorSelection::add_invulnerable(RuntimeOrigin::signed(1), 3),71 BadOrigin72 );7374 // cannot set invulnerables without associated validator keys75 assert_noop!(76 CollatorSelection::add_invulnerable(RuntimeOrigin::signed(RootAccount::get()), 7),77 Error::<Test>::ValidatorNotRegistered78 );79 });80}8182#[test]83fn it_should_remove_invulnerables() {84 new_test_ext().execute_with(|| {85 assert_ok!(CollatorSelection::add_invulnerable(86 RuntimeOrigin::signed(RootAccount::get()),87 188 ));89 assert_ok!(CollatorSelection::add_invulnerable(90 RuntimeOrigin::signed(RootAccount::get()),91 292 ));9394 // cannot remove with non-root.95 assert_noop!(96 CollatorSelection::remove_invulnerable(RuntimeOrigin::signed(1), 3),97 BadOrigin98 );99100 assert_ok!(CollatorSelection::remove_invulnerable(101 RuntimeOrigin::signed(RootAccount::get()),102 2103 ));104 assert_eq!(CollatorSelection::invulnerables(), vec![1]);105106 // cannot remove an invulnerable if there would be 0 invulnerables.107 assert_noop!(108 CollatorSelection::remove_invulnerable(RuntimeOrigin::signed(RootAccount::get()), 1),109 Error::<Test>::TooFewInvulnerables110 );111 });112}113114#[test]115fn set_desired_candidates_works() {116 new_test_ext().execute_with(|| {117 // given118 assert_eq!(CollatorSelection::desired_candidates(), 2);119120 // can set121 assert_ok!(CollatorSelection::set_desired_candidates(122 RuntimeOrigin::signed(RootAccount::get()),123 7124 ));125 assert_eq!(CollatorSelection::desired_candidates(), 7);126127 // rejects bad origin128 assert_noop!(129 CollatorSelection::set_desired_candidates(RuntimeOrigin::signed(1), 8),130 BadOrigin131 );132 });133}134135#[test]136fn set_candidacy_bond() {137 new_test_ext().execute_with(|| {138 // given139 assert_eq!(CollatorSelection::candidacy_bond(), 10);140141 // can set142 assert_ok!(CollatorSelection::set_candidacy_bond(143 RuntimeOrigin::signed(RootAccount::get()),144 7145 ));146 assert_eq!(CollatorSelection::candidacy_bond(), 7);147148 // rejects bad origin.149 assert_noop!(150 CollatorSelection::set_candidacy_bond(RuntimeOrigin::signed(1), 8),151 BadOrigin152 );153 });154}155156#[test]157fn cannot_register_candidate_if_too_many() {158 new_test_ext().execute_with(|| {159 // reset desired candidates:160 <crate::DesiredCandidates<Test>>::put(0);161162 // can't accept anyone anymore.163 assert_noop!(164 CollatorSelection::register_as_candidate(RuntimeOrigin::signed(3)),165 Error::<Test>::TooManyCandidates,166 );167168 // reset desired candidates:169 <crate::DesiredCandidates<Test>>::put(1);170 assert_ok!(CollatorSelection::register_as_candidate(171 RuntimeOrigin::signed(4)172 ));173174 // but no more175 assert_noop!(176 CollatorSelection::register_as_candidate(RuntimeOrigin::signed(5)),177 Error::<Test>::TooManyCandidates,178 );179 })180}181182#[test]183fn cannot_unregister_candidate_if_too_few() {184 new_test_ext().execute_with(|| {185 // reset desired candidates:186 <crate::DesiredCandidates<Test>>::put(1);187 assert_ok!(CollatorSelection::register_as_candidate(188 RuntimeOrigin::signed(4)189 ));190191 // can not remove too few192 assert_noop!(193 CollatorSelection::leave_intent(RuntimeOrigin::signed(4)),194 Error::<Test>::TooFewCandidates,195 );196 })197}198199#[test]200fn cannot_register_as_candidate_if_invulnerable() {201 new_test_ext().execute_with(|| {202 assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);203204 // can't 1 because it is invulnerable.205 assert_noop!(206 CollatorSelection::register_as_candidate(RuntimeOrigin::signed(1)),207 Error::<Test>::AlreadyInvulnerable,208 );209 })210}211212#[test]213fn cannot_register_as_candidate_if_keys_not_registered() {214 new_test_ext().execute_with(|| {215 // can't 7 because keys not registered.216 assert_noop!(217 CollatorSelection::register_as_candidate(RuntimeOrigin::signed(7)),218 Error::<Test>::ValidatorNotRegistered219 );220 })221}222223#[test]224fn cannot_register_dupe_candidate() {225 new_test_ext().execute_with(|| {226 // can add 3 as candidate227 assert_ok!(CollatorSelection::register_as_candidate(228 RuntimeOrigin::signed(3)229 ));230 let addition = CandidateInfo {231 who: 3,232 deposit: 10,233 };234 assert_eq!(CollatorSelection::candidates(), vec![addition]);235 assert_eq!(CollatorSelection::last_authored_block(3), 10);236 assert_eq!(Balances::free_balance(3), 90);237238 // but no more239 assert_noop!(240 CollatorSelection::register_as_candidate(RuntimeOrigin::signed(3)),241 Error::<Test>::AlreadyCandidate,242 );243 })244}245246#[test]247fn cannot_register_as_candidate_if_poor() {248 new_test_ext().execute_with(|| {249 assert_eq!(Balances::free_balance(&3), 100);250 assert_eq!(Balances::free_balance(&33), 0);251252 // works253 assert_ok!(CollatorSelection::register_as_candidate(254 RuntimeOrigin::signed(3)255 ));256257 // poor258 assert_noop!(259 CollatorSelection::register_as_candidate(RuntimeOrigin::signed(33)),260 BalancesError::<Test>::InsufficientBalance,261 );262 });263}264265#[test]266fn register_as_candidate_works() {267 new_test_ext().execute_with(|| {268 // given269 assert_eq!(CollatorSelection::desired_candidates(), 2);270 assert_eq!(CollatorSelection::candidacy_bond(), 10);271 assert_eq!(CollatorSelection::candidates(), Vec::new());272 assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);273274 // take two endowed, non-invulnerables accounts.275 assert_eq!(Balances::free_balance(&3), 100);276 assert_eq!(Balances::free_balance(&4), 100);277278 assert_ok!(CollatorSelection::register_as_candidate(279 RuntimeOrigin::signed(3)280 ));281 assert_ok!(CollatorSelection::register_as_candidate(282 RuntimeOrigin::signed(4)283 ));284285 assert_eq!(Balances::free_balance(&3), 90);286 assert_eq!(Balances::free_balance(&4), 90);287288 assert_eq!(CollatorSelection::candidates().len(), 2);289 });290}291292#[test]293fn leave_intent() {294 new_test_ext().execute_with(|| {295 // register a candidate.296 assert_ok!(CollatorSelection::register_as_candidate(297 RuntimeOrigin::signed(3)298 ));299 assert_eq!(Balances::free_balance(3), 90);300301 // register too so can leave above min candidates302 assert_ok!(CollatorSelection::register_as_candidate(303 RuntimeOrigin::signed(5)304 ));305 assert_eq!(Balances::free_balance(5), 90);306307 // cannot leave if not candidate.308 assert_noop!(309 CollatorSelection::leave_intent(RuntimeOrigin::signed(4)),310 Error::<Test>::NotCandidate311 );312313 // bond is returned314 assert_ok!(CollatorSelection::leave_intent(RuntimeOrigin::signed(3)));315 assert_eq!(Balances::free_balance(3), 100);316 assert_eq!(CollatorSelection::last_authored_block(3), 0);317 });318}319320#[test]321fn authorship_event_handler() {322 new_test_ext().execute_with(|| {323 // put 100 in the pot + 5 for ED324 Balances::make_free_balance_be(&CollatorSelection::account_id(), 105);325326 // 4 is the default author.327 assert_eq!(Balances::free_balance(4), 100);328 assert_ok!(CollatorSelection::register_as_candidate(329 RuntimeOrigin::signed(4)330 ));331 // triggers `note_author`332 Authorship::on_initialize(1);333334 let collator = CandidateInfo {335 who: 4,336 deposit: 10,337 };338339 assert_eq!(CollatorSelection::candidates(), vec![collator]);340 assert_eq!(CollatorSelection::last_authored_block(4), 0);341342 // half of the pot goes to the collator who's the author (4 in tests).343 assert_eq!(Balances::free_balance(4), 140);344 // half + ED stays.345 assert_eq!(Balances::free_balance(CollatorSelection::account_id()), 55);346 });347}348349#[test]350fn fees_edgecases() {351 new_test_ext().execute_with(|| {352 // Nothing panics, no reward when no ED in balance353 Authorship::on_initialize(1);354 // put some money into the pot at ED355 Balances::make_free_balance_be(&CollatorSelection::account_id(), 5);356 // 4 is the default author.357 assert_eq!(Balances::free_balance(4), 100);358 assert_ok!(CollatorSelection::register_as_candidate(359 RuntimeOrigin::signed(4)360 ));361 // triggers `note_author`362 Authorship::on_initialize(1);363364 let collator = CandidateInfo {365 who: 4,366 deposit: 10,367 };368369 assert_eq!(CollatorSelection::candidates(), vec![collator]);370 assert_eq!(CollatorSelection::last_authored_block(4), 0);371 // Nothing received372 assert_eq!(Balances::free_balance(4), 90);373 // all fee stays374 assert_eq!(Balances::free_balance(CollatorSelection::account_id()), 5);375 });376}377378#[test]379fn session_management_works() {380 new_test_ext().execute_with(|| {381 initialize_to_block(1);382383 assert_eq!(SessionChangeBlock::get(), 0);384 assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);385386 initialize_to_block(4);387388 assert_eq!(SessionChangeBlock::get(), 0);389 assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);390391 // add a new collator392 assert_ok!(CollatorSelection::register_as_candidate(393 RuntimeOrigin::signed(3)394 ));395396 // session won't see this.397 assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);398 // but we have a new candidate.399 assert_eq!(CollatorSelection::candidates().len(), 1);400401 initialize_to_block(10);402 assert_eq!(SessionChangeBlock::get(), 10);403 // pallet-session has 1 session delay; current validators are the same.404 assert_eq!(Session::validators(), vec![1, 2]);405 // queued ones are changed, and now we have 3.406 assert_eq!(Session::queued_keys().len(), 3);407 // session handlers (aura, et. al.) cannot see this yet.408 assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);409410 initialize_to_block(20);411 assert_eq!(SessionChangeBlock::get(), 20);412 // changed are now reflected to session handlers.413 assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 3]);414 });415}416417#[test]418fn kick_mechanism() {419 new_test_ext().execute_with(|| {420 // add a new collator421 assert_ok!(CollatorSelection::register_as_candidate(422 RuntimeOrigin::signed(3)423 ));424 assert_ok!(CollatorSelection::register_as_candidate(425 RuntimeOrigin::signed(4)426 ));427 initialize_to_block(10);428 assert_eq!(CollatorSelection::candidates().len(), 2);429 initialize_to_block(20);430 assert_eq!(SessionChangeBlock::get(), 20);431 // 4 authored this block, gets to stay 3 was kicked432 assert_eq!(CollatorSelection::candidates().len(), 1);433 // 3 will be kicked after 1 session delay434 assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 3, 4]);435 let collator = CandidateInfo {436 who: 4,437 deposit: 10,438 };439 assert_eq!(CollatorSelection::candidates(), vec![collator]);440 assert_eq!(CollatorSelection::kick_threshold(), 1);441 assert_eq!(CollatorSelection::last_authored_block(4), 20);442 initialize_to_block(30);443 // 3 gets kicked after 1 session delay444 assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 4]);445 // kicked collator gets funds back446 assert_eq!(Balances::free_balance(3), 100);447 });448}449450#[test]451fn should_not_kick_mechanism_too_few() {452 new_test_ext().execute_with(|| {453 // add a new collator454 assert_ok!(CollatorSelection::register_as_candidate(455 RuntimeOrigin::signed(3)456 ));457 assert_ok!(CollatorSelection::register_as_candidate(458 RuntimeOrigin::signed(5)459 ));460 initialize_to_block(10);461 assert_eq!(CollatorSelection::candidates().len(), 2);462 initialize_to_block(20);463 assert_eq!(SessionChangeBlock::get(), 20);464 // 4 authored this block, 5 gets to stay too few 3 was kicked465 assert_eq!(CollatorSelection::candidates().len(), 1);466 // 3 will be kicked after 1 session delay467 assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 3, 5]);468 let collator = CandidateInfo {469 who: 5,470 deposit: 10,471 };472 assert_eq!(CollatorSelection::candidates(), vec![collator]);473 assert_eq!(CollatorSelection::last_authored_block(4), 20);474 initialize_to_block(30);475 // 3 gets kicked after 1 session delay476 assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 5]);477 // kicked collator gets funds back478 assert_eq!(Balances::free_balance(3), 100);479 });480}481482#[test]483#[should_panic = "duplicate invulnerables in genesis."]484fn cannot_set_genesis_value_twice() {485 sp_tracing::try_init_simple();486 let mut t = frame_system::GenesisConfig::default()487 .build_storage::<Test>()488 .unwrap();489 let invulnerables = vec![1, 1];490491 let collator_selection = collator_selection::GenesisConfig::<Test> {492 desired_candidates: 2,493 candidacy_bond: 10,494 kick_threshold: 1,495 invulnerables,496 };497 // collator selection must be initialized before session.498 collator_selection.assimilate_storage(&mut t).unwrap();499}tests/src/collatorSelection.seqtest.tsdiffbeforeafterboth--- a/tests/src/collatorSelection.seqtest.ts
+++ b/tests/src/collatorSelection.seqtest.ts
@@ -64,6 +64,10 @@
before(async function() {
await usingPlaygrounds(async (helper, privateKey) => {
+ // todo:collator see again if blocks start to be finalized in dev mode
+ // Skip the collator block production in dev mode, since the blocks are sealed automatically.
+ if (await helper.arrange.isDevNode()) this.skip();
+
alice = await privateKey('//Alice');
bob = await privateKey('//Bob');
charlie = await privateKey('//Charlie');
@@ -141,7 +145,7 @@
after(async () => {
await usingPlaygrounds(async (helper) => {
- if (helper.fetchMissingPalletNames([Pallets.CollatorSelection]).length != 0) return;
+ if (await helper.arrange.isDevNode()) return;
let nonce = await helper.chain.getNonce(superuser.address);
await Promise.all([
@@ -161,7 +165,7 @@
// todo:collator make sure that there is enough session time for a set of tests
// 28 non-functioning collators, teehee.
- describe.skip('Addition and removal of invulnerables', () => {
+ describe('Addition and removal of invulnerables', () => {
before(async function() {
await resetInvulnerables();
});
@@ -261,7 +265,14 @@
expect(await helper.collatorSelection.getInvulnerables()).to.have.all.members(invulnerables);
});
});
+
+ after(async () => {
+ // eslint-disable-next-line require-await
+ await usingPlaygrounds(async (helper) => {
+ if (helper.fetchMissingPalletNames([Pallets.CollatorSelection]).length != 0) return;
- // todo:collator after
+ // todo:collator after
+ });
+ });
});
});
\ No newline at end of file