git.delta.rocks / unique-network / refs/commits / 1e14fe80093b

difftreelog

source

pallets/collator-selection/src/tests.rs13.1 KiBsourcehistory
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#[test]54fn it_should_set_invulnerables() {55	new_test_ext().execute_with(|| {56		let new_set = vec![1, 2, 3, 4];57		assert_ok!(CollatorSelection::set_invulnerables(58			RuntimeOrigin::signed(RootAccount::get()),59			new_set.clone()60		));61		assert_eq!(CollatorSelection::invulnerables(), new_set);6263		// cannot set with non-root.64		assert_noop!(65			CollatorSelection::set_invulnerables(RuntimeOrigin::signed(1), new_set.clone()),66			BadOrigin67		);6869		// cannot set invulnerables without associated validator keys70		let invulnerables = vec![7];71		assert_noop!(72			CollatorSelection::set_invulnerables(73				RuntimeOrigin::signed(RootAccount::get()),74				invulnerables.clone()75			),76			Error::<Test>::ValidatorNotRegistered77		);78	});79}8081#[test]82fn set_desired_candidates_works() {83	new_test_ext().execute_with(|| {84		// given85		assert_eq!(CollatorSelection::desired_candidates(), 2);8687		// can set88		assert_ok!(CollatorSelection::set_desired_candidates(89			RuntimeOrigin::signed(RootAccount::get()),90			791		));92		assert_eq!(CollatorSelection::desired_candidates(), 7);9394		// rejects bad origin95		assert_noop!(96			CollatorSelection::set_desired_candidates(RuntimeOrigin::signed(1), 8),97			BadOrigin98		);99	});100}101102#[test]103fn set_candidacy_bond() {104	new_test_ext().execute_with(|| {105		// given106		assert_eq!(CollatorSelection::candidacy_bond(), 10);107108		// can set109		assert_ok!(CollatorSelection::set_candidacy_bond(110			RuntimeOrigin::signed(RootAccount::get()),111			7112		));113		assert_eq!(CollatorSelection::candidacy_bond(), 7);114115		// rejects bad origin.116		assert_noop!(117			CollatorSelection::set_candidacy_bond(RuntimeOrigin::signed(1), 8),118			BadOrigin119		);120	});121}122123#[test]124fn cannot_register_candidate_if_too_many() {125	new_test_ext().execute_with(|| {126		// reset desired candidates:127		<crate::DesiredCandidates<Test>>::put(0);128129		// can't accept anyone anymore.130		assert_noop!(131			CollatorSelection::register_as_candidate(RuntimeOrigin::signed(3)),132			Error::<Test>::TooManyCandidates,133		);134135		// reset desired candidates:136		<crate::DesiredCandidates<Test>>::put(1);137		assert_ok!(CollatorSelection::register_as_candidate(138			RuntimeOrigin::signed(4)139		));140141		// but no more142		assert_noop!(143			CollatorSelection::register_as_candidate(RuntimeOrigin::signed(5)),144			Error::<Test>::TooManyCandidates,145		);146	})147}148149#[test]150fn cannot_unregister_candidate_if_too_few() {151	new_test_ext().execute_with(|| {152		// reset desired candidates:153		<crate::DesiredCandidates<Test>>::put(1);154		assert_ok!(CollatorSelection::register_as_candidate(155			RuntimeOrigin::signed(4)156		));157158		// can not remove too few159		assert_noop!(160			CollatorSelection::leave_intent(RuntimeOrigin::signed(4)),161			Error::<Test>::TooFewCandidates,162		);163	})164}165166#[test]167fn cannot_register_as_candidate_if_invulnerable() {168	new_test_ext().execute_with(|| {169		assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);170171		// can't 1 because it is invulnerable.172		assert_noop!(173			CollatorSelection::register_as_candidate(RuntimeOrigin::signed(1)),174			Error::<Test>::AlreadyInvulnerable,175		);176	})177}178179#[test]180fn cannot_register_as_candidate_if_keys_not_registered() {181	new_test_ext().execute_with(|| {182		// can't 7 because keys not registered.183		assert_noop!(184			CollatorSelection::register_as_candidate(RuntimeOrigin::signed(7)),185			Error::<Test>::ValidatorNotRegistered186		);187	})188}189190#[test]191fn cannot_register_dupe_candidate() {192	new_test_ext().execute_with(|| {193		// can add 3 as candidate194		assert_ok!(CollatorSelection::register_as_candidate(195			RuntimeOrigin::signed(3)196		));197		let addition = CandidateInfo {198			who: 3,199			deposit: 10,200		};201		assert_eq!(CollatorSelection::candidates(), vec![addition]);202		assert_eq!(CollatorSelection::last_authored_block(3), 10);203		assert_eq!(Balances::free_balance(3), 90);204205		// but no more206		assert_noop!(207			CollatorSelection::register_as_candidate(RuntimeOrigin::signed(3)),208			Error::<Test>::AlreadyCandidate,209		);210	})211}212213#[test]214fn cannot_register_as_candidate_if_poor() {215	new_test_ext().execute_with(|| {216		assert_eq!(Balances::free_balance(&3), 100);217		assert_eq!(Balances::free_balance(&33), 0);218219		// works220		assert_ok!(CollatorSelection::register_as_candidate(221			RuntimeOrigin::signed(3)222		));223224		// poor225		assert_noop!(226			CollatorSelection::register_as_candidate(RuntimeOrigin::signed(33)),227			BalancesError::<Test>::InsufficientBalance,228		);229	});230}231232#[test]233fn register_as_candidate_works() {234	new_test_ext().execute_with(|| {235		// given236		assert_eq!(CollatorSelection::desired_candidates(), 2);237		assert_eq!(CollatorSelection::candidacy_bond(), 10);238		assert_eq!(CollatorSelection::candidates(), Vec::new());239		assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);240241		// take two endowed, non-invulnerables accounts.242		assert_eq!(Balances::free_balance(&3), 100);243		assert_eq!(Balances::free_balance(&4), 100);244245		assert_ok!(CollatorSelection::register_as_candidate(246			RuntimeOrigin::signed(3)247		));248		assert_ok!(CollatorSelection::register_as_candidate(249			RuntimeOrigin::signed(4)250		));251252		assert_eq!(Balances::free_balance(&3), 90);253		assert_eq!(Balances::free_balance(&4), 90);254255		assert_eq!(CollatorSelection::candidates().len(), 2);256	});257}258259#[test]260fn leave_intent() {261	new_test_ext().execute_with(|| {262		// register a candidate.263		assert_ok!(CollatorSelection::register_as_candidate(264			RuntimeOrigin::signed(3)265		));266		assert_eq!(Balances::free_balance(3), 90);267268		// register too so can leave above min candidates269		assert_ok!(CollatorSelection::register_as_candidate(270			RuntimeOrigin::signed(5)271		));272		assert_eq!(Balances::free_balance(5), 90);273274		// cannot leave if not candidate.275		assert_noop!(276			CollatorSelection::leave_intent(RuntimeOrigin::signed(4)),277			Error::<Test>::NotCandidate278		);279280		// bond is returned281		assert_ok!(CollatorSelection::leave_intent(RuntimeOrigin::signed(3)));282		assert_eq!(Balances::free_balance(3), 100);283		assert_eq!(CollatorSelection::last_authored_block(3), 0);284	});285}286287#[test]288fn authorship_event_handler() {289	new_test_ext().execute_with(|| {290		// put 100 in the pot + 5 for ED291		Balances::make_free_balance_be(&CollatorSelection::account_id(), 105);292293		// 4 is the default author.294		assert_eq!(Balances::free_balance(4), 100);295		assert_ok!(CollatorSelection::register_as_candidate(296			RuntimeOrigin::signed(4)297		));298		// triggers `note_author`299		Authorship::on_initialize(1);300301		let collator = CandidateInfo {302			who: 4,303			deposit: 10,304		};305306		assert_eq!(CollatorSelection::candidates(), vec![collator]);307		assert_eq!(CollatorSelection::last_authored_block(4), 0);308309		// half of the pot goes to the collator who's the author (4 in tests).310		assert_eq!(Balances::free_balance(4), 140);311		// half + ED stays.312		assert_eq!(Balances::free_balance(CollatorSelection::account_id()), 55);313	});314}315316#[test]317fn fees_edgecases() {318	new_test_ext().execute_with(|| {319		// Nothing panics, no reward when no ED in balance320		Authorship::on_initialize(1);321		// put some money into the pot at ED322		Balances::make_free_balance_be(&CollatorSelection::account_id(), 5);323		// 4 is the default author.324		assert_eq!(Balances::free_balance(4), 100);325		assert_ok!(CollatorSelection::register_as_candidate(326			RuntimeOrigin::signed(4)327		));328		// triggers `note_author`329		Authorship::on_initialize(1);330331		let collator = CandidateInfo {332			who: 4,333			deposit: 10,334		};335336		assert_eq!(CollatorSelection::candidates(), vec![collator]);337		assert_eq!(CollatorSelection::last_authored_block(4), 0);338		// Nothing received339		assert_eq!(Balances::free_balance(4), 90);340		// all fee stays341		assert_eq!(Balances::free_balance(CollatorSelection::account_id()), 5);342	});343}344345#[test]346fn session_management_works() {347	new_test_ext().execute_with(|| {348		initialize_to_block(1);349350		assert_eq!(SessionChangeBlock::get(), 0);351		assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);352353		initialize_to_block(4);354355		assert_eq!(SessionChangeBlock::get(), 0);356		assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);357358		// add a new collator359		assert_ok!(CollatorSelection::register_as_candidate(360			RuntimeOrigin::signed(3)361		));362363		// session won't see this.364		assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);365		// but we have a new candidate.366		assert_eq!(CollatorSelection::candidates().len(), 1);367368		initialize_to_block(10);369		assert_eq!(SessionChangeBlock::get(), 10);370		// pallet-session has 1 session delay; current validators are the same.371		assert_eq!(Session::validators(), vec![1, 2]);372		// queued ones are changed, and now we have 3.373		assert_eq!(Session::queued_keys().len(), 3);374		// session handlers (aura, et. al.) cannot see this yet.375		assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);376377		initialize_to_block(20);378		assert_eq!(SessionChangeBlock::get(), 20);379		// changed are now reflected to session handlers.380		assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 3]);381	});382}383384#[test]385fn kick_mechanism() {386	new_test_ext().execute_with(|| {387		// add a new collator388		assert_ok!(CollatorSelection::register_as_candidate(389			RuntimeOrigin::signed(3)390		));391		assert_ok!(CollatorSelection::register_as_candidate(392			RuntimeOrigin::signed(4)393		));394		initialize_to_block(10);395		assert_eq!(CollatorSelection::candidates().len(), 2);396		initialize_to_block(20);397		assert_eq!(SessionChangeBlock::get(), 20);398		// 4 authored this block, gets to stay 3 was kicked399		assert_eq!(CollatorSelection::candidates().len(), 1);400		// 3 will be kicked after 1 session delay401		assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 3, 4]);402		let collator = CandidateInfo {403			who: 4,404			deposit: 10,405		};406		assert_eq!(CollatorSelection::candidates(), vec![collator]);407		assert_eq!(CollatorSelection::last_authored_block(4), 20);408		initialize_to_block(30);409		// 3 gets kicked after 1 session delay410		assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 4]);411		// kicked collator gets funds back412		assert_eq!(Balances::free_balance(3), 100);413	});414}415416#[test]417fn should_not_kick_mechanism_too_few() {418	new_test_ext().execute_with(|| {419		// add a new collator420		assert_ok!(CollatorSelection::register_as_candidate(421			RuntimeOrigin::signed(3)422		));423		assert_ok!(CollatorSelection::register_as_candidate(424			RuntimeOrigin::signed(5)425		));426		initialize_to_block(10);427		assert_eq!(CollatorSelection::candidates().len(), 2);428		initialize_to_block(20);429		assert_eq!(SessionChangeBlock::get(), 20);430		// 4 authored this block, 5 gets to stay too few 3 was kicked431		assert_eq!(CollatorSelection::candidates().len(), 1);432		// 3 will be kicked after 1 session delay433		assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 3, 5]);434		let collator = CandidateInfo {435			who: 5,436			deposit: 10,437		};438		assert_eq!(CollatorSelection::candidates(), vec![collator]);439		assert_eq!(CollatorSelection::last_authored_block(4), 20);440		initialize_to_block(30);441		// 3 gets kicked after 1 session delay442		assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 5]);443		// kicked collator gets funds back444		assert_eq!(Balances::free_balance(3), 100);445	});446}447448#[test]449#[should_panic = "duplicate invulnerables in genesis."]450fn cannot_set_genesis_value_twice() {451	sp_tracing::try_init_simple();452	let mut t = frame_system::GenesisConfig::default()453		.build_storage::<Test>()454		.unwrap();455	let invulnerables = vec![1, 1];456457	let collator_selection = collator_selection::GenesisConfig::<Test> {458		desired_candidates: 2,459		candidacy_bond: 10,460		invulnerables,461	};462	// collator selection must be initialized before session.463	collator_selection.assimilate_storage(&mut t).unwrap();464}