From b64b17536a23ddbf2254e8a7e08823fe65eedb41 Mon Sep 17 00:00:00 2001
From: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
Date: Fri, 20 Nov 2020 18:54:19 +0100
Subject: [PATCH] Thread-local parameter_types for testing. (#7542)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* Thread-local parameter_types for testing.

* Better docs.

* Some minors

* Merge'em

* Update frame/support/src/lib.rs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Align more to basti's trick

* Update frame/support/src/lib.rs

* Update frame/support/src/lib.rs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
Co-authored-by: Bastian Köcher <git@kchr.de>
---
 .../frame/balances/src/tests_composite.rs     | 12 +--
 substrate/frame/balances/src/tests_local.rs   | 13 +--
 substrate/frame/contracts/src/tests.rs        | 13 +--
 substrate/frame/democracy/src/tests.rs        | 16 +---
 substrate/frame/elections-phragmen/src/lib.rs | 38 ++------
 substrate/frame/elections/src/mock.rs         | 46 +++-------
 substrate/frame/elections/src/tests.rs        | 12 +--
 substrate/frame/membership/src/lib.rs         |  8 +-
 substrate/frame/staking/src/mock.rs           | 62 ++-----------
 substrate/frame/support/src/lib.rs            | 92 +++++++++++++++++--
 .../frame/transaction-payment/src/lib.rs      | 23 +----
 substrate/frame/vesting/src/lib.rs            | 10 +-
 12 files changed, 128 insertions(+), 217 deletions(-)

diff --git a/substrate/frame/balances/src/tests_composite.rs b/substrate/frame/balances/src/tests_composite.rs
index 88b73b47273..fd4ba1fd3c3 100644
--- a/substrate/frame/balances/src/tests_composite.rs
+++ b/substrate/frame/balances/src/tests_composite.rs
@@ -27,10 +27,8 @@ use sp_runtime::{
 use sp_core::H256;
 use sp_io;
 use frame_support::{impl_outer_origin, impl_outer_event, parameter_types};
-use frame_support::traits::Get;
 use frame_support::weights::{Weight, DispatchInfo, IdentityFee};
 use pallet_transaction_payment::CurrencyAdapter;
-use std::cell::RefCell;
 use crate::{GenesisConfig, Module, Trait, decl_tests, tests::CallWithDispatchInfo};
 
 use frame_system as system;
@@ -49,15 +47,6 @@ impl_outer_event! {
 	}
 }
 
-thread_local! {
-	static EXISTENTIAL_DEPOSIT: RefCell<u64> = RefCell::new(0);
-}
-
-pub struct ExistentialDeposit;
-impl Get<u64> for ExistentialDeposit {
-	fn get() -> u64 { EXISTENTIAL_DEPOSIT.with(|v| *v.borrow()) }
-}
-
 // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub struct Test;
@@ -66,6 +55,7 @@ parameter_types! {
 	pub const MaximumBlockWeight: Weight = 1024;
 	pub const MaximumBlockLength: u32 = 2 * 1024;
 	pub const AvailableBlockRatio: Perbill = Perbill::one();
+	pub static ExistentialDeposit: u64 = 0;
 }
 impl frame_system::Trait for Test {
 	type BaseCallFilter = ();
diff --git a/substrate/frame/balances/src/tests_local.rs b/substrate/frame/balances/src/tests_local.rs
index 319fb3640b4..c0a5d23ff1a 100644
--- a/substrate/frame/balances/src/tests_local.rs
+++ b/substrate/frame/balances/src/tests_local.rs
@@ -27,9 +27,8 @@ use sp_runtime::{
 use sp_core::H256;
 use sp_io;
 use frame_support::{impl_outer_origin, impl_outer_event, parameter_types};
-use frame_support::traits::{Get, StorageMapShim};
+use frame_support::traits::StorageMapShim;
 use frame_support::weights::{Weight, DispatchInfo, IdentityFee};
-use std::cell::RefCell;
 use crate::{GenesisConfig, Module, Trait, decl_tests, tests::CallWithDispatchInfo};
 use pallet_transaction_payment::CurrencyAdapter;
 
@@ -49,15 +48,6 @@ impl_outer_event! {
 	}
 }
 
-thread_local! {
-	static EXISTENTIAL_DEPOSIT: RefCell<u64> = RefCell::new(0);
-}
-
-pub struct ExistentialDeposit;
-impl Get<u64> for ExistentialDeposit {
-	fn get() -> u64 { EXISTENTIAL_DEPOSIT.with(|v| *v.borrow()) }
-}
-
 // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub struct Test;
@@ -66,6 +56,7 @@ parameter_types! {
 	pub const MaximumBlockWeight: Weight = 1024;
 	pub const MaximumBlockLength: u32 = 2 * 1024;
 	pub const AvailableBlockRatio: Perbill = Perbill::one();
+	pub static ExistentialDeposit: u64 = 0;
 }
 impl frame_system::Trait for Test {
 	type BaseCallFilter = ();
diff --git a/substrate/frame/contracts/src/tests.rs b/substrate/frame/contracts/src/tests.rs
index c2d9ed66425..05e46a3ab15 100644
--- a/substrate/frame/contracts/src/tests.rs
+++ b/substrate/frame/contracts/src/tests.rs
@@ -30,11 +30,10 @@ use sp_runtime::{
 use frame_support::{
 	assert_ok, assert_err_ignore_postinfo, impl_outer_dispatch, impl_outer_event,
 	impl_outer_origin, parameter_types, StorageMap, StorageValue,
-	traits::{Currency, Get, ReservableCurrency},
+	traits::{Currency, ReservableCurrency},
 	weights::{Weight, PostDispatchInfo},
 	dispatch::DispatchErrorWithPostInfo,
 };
-use std::cell::RefCell;
 use frame_system::{self as system, EventRecord, Phase};
 
 mod contracts {
@@ -99,15 +98,6 @@ pub mod test_utils {
 	}
 }
 
-thread_local! {
-	static EXISTENTIAL_DEPOSIT: RefCell<u64> = RefCell::new(0);
-}
-
-pub struct ExistentialDeposit;
-impl Get<u64> for ExistentialDeposit {
-	fn get() -> u64 { EXISTENTIAL_DEPOSIT.with(|v| *v.borrow()) }
-}
-
 #[derive(Clone, Eq, PartialEq, Debug)]
 pub struct Test;
 parameter_types! {
@@ -115,6 +105,7 @@ parameter_types! {
 	pub const MaximumBlockWeight: Weight = 1024;
 	pub const MaximumBlockLength: u32 = 2 * 1024;
 	pub const AvailableBlockRatio: Perbill = Perbill::one();
+	pub static ExistentialDeposit: u64 = 0;
 }
 impl frame_system::Trait for Test {
 	type BaseCallFilter = ();
diff --git a/substrate/frame/democracy/src/tests.rs b/substrate/frame/democracy/src/tests.rs
index bcc7099bb34..25209901109 100644
--- a/substrate/frame/democracy/src/tests.rs
+++ b/substrate/frame/democracy/src/tests.rs
@@ -18,7 +18,6 @@
 //! The crate's tests.
 
 use super::*;
-use std::cell::RefCell;
 use codec::Encode;
 use frame_support::{
 	impl_outer_origin, impl_outer_dispatch, assert_noop, assert_ok, parameter_types,
@@ -154,6 +153,8 @@ parameter_types! {
 	pub const CooloffPeriod: u64 = 2;
 	pub const MaxVotes: u32 = 100;
 	pub const MaxProposals: u32 = MAX_PROPOSALS;
+	pub static PreimageByteDeposit: u64 = 0;
+	pub static InstantAllowed: bool = false;
 }
 ord_parameter_types! {
 	pub const One: u64 = 1;
@@ -171,18 +172,7 @@ impl Contains<u64> for OneToFive {
 	#[cfg(feature = "runtime-benchmarks")]
 	fn add(_m: &u64) {}
 }
-thread_local! {
-	static PREIMAGE_BYTE_DEPOSIT: RefCell<u64> = RefCell::new(0);
-	static INSTANT_ALLOWED: RefCell<bool> = RefCell::new(false);
-}
-pub struct PreimageByteDeposit;
-impl Get<u64> for PreimageByteDeposit {
-	fn get() -> u64 { PREIMAGE_BYTE_DEPOSIT.with(|v| *v.borrow()) }
-}
-pub struct InstantAllowed;
-impl Get<bool> for InstantAllowed {
-	fn get() -> bool { INSTANT_ALLOWED.with(|v| *v.borrow()) }
-}
+
 impl super::Trait for Test {
 	type Proposal = Call;
 	type Event = Event;
diff --git a/substrate/frame/elections-phragmen/src/lib.rs b/substrate/frame/elections-phragmen/src/lib.rs
index be47b5adcce..8279f9cf11f 100644
--- a/substrate/frame/elections-phragmen/src/lib.rs
+++ b/substrate/frame/elections-phragmen/src/lib.rs
@@ -1058,7 +1058,6 @@ impl<T: Trait> ContainsLengthBound for Module<T> {
 #[cfg(test)]
 mod tests {
 	use super::*;
-	use std::cell::RefCell;
 	use frame_support::{assert_ok, assert_noop, assert_err_with_weight, parameter_types,
 		weights::Weight,
 	};
@@ -1123,36 +1122,13 @@ mod tests {
 		pub const CandidacyBond: u64 = 3;
 	}
 
-	thread_local! {
-		static VOTING_BOND: RefCell<u64> = RefCell::new(2);
-		static DESIRED_MEMBERS: RefCell<u32> = RefCell::new(2);
-		static DESIRED_RUNNERS_UP: RefCell<u32> = RefCell::new(2);
-		static TERM_DURATION: RefCell<u64> = RefCell::new(5);
-	}
-
-	pub struct VotingBond;
-	impl Get<u64> for VotingBond {
-		fn get() -> u64 { VOTING_BOND.with(|v| *v.borrow()) }
-	}
-
-	pub struct DesiredMembers;
-	impl Get<u32> for DesiredMembers {
-		fn get() -> u32 { DESIRED_MEMBERS.with(|v| *v.borrow()) }
-	}
-
-	pub struct DesiredRunnersUp;
-	impl Get<u32> for DesiredRunnersUp {
-		fn get() -> u32 { DESIRED_RUNNERS_UP.with(|v| *v.borrow()) }
-	}
-
-	pub struct TermDuration;
-	impl Get<u64> for TermDuration {
-		fn get() -> u64 { TERM_DURATION.with(|v| *v.borrow()) }
-	}
-
-	thread_local! {
-		pub static MEMBERS: RefCell<Vec<u64>> = RefCell::new(vec![]);
-		pub static PRIME: RefCell<Option<u64>> = RefCell::new(None);
+	frame_support::parameter_types! {
+		pub static VotingBond: u64 = 2;
+		pub static DesiredMembers: u32 = 2;
+		pub static DesiredRunnersUp: u32 = 2;
+		pub static TermDuration: u64 = 5;
+		pub static Members: Vec<u64> = vec![];
+		pub static Prime: Option<u64> = None;
 	}
 
 	pub struct TestChangeMembers;
diff --git a/substrate/frame/elections/src/mock.rs b/substrate/frame/elections/src/mock.rs
index deec77da7b8..0d57089af5e 100644
--- a/substrate/frame/elections/src/mock.rs
+++ b/substrate/frame/elections/src/mock.rs
@@ -19,10 +19,9 @@
 
 #![cfg(test)]
 
-use std::cell::RefCell;
 use frame_support::{
 	StorageValue, StorageMap, parameter_types, assert_ok,
-	traits::{Get, ChangeMembers, Currency, LockIdentifier},
+	traits::{ChangeMembers, Currency, LockIdentifier},
 	weights::Weight,
 };
 use sp_core::H256;
@@ -85,34 +84,11 @@ parameter_types! {
 	pub const InactiveGracePeriod: u32 = 1;
 	pub const VotingPeriod: u64 = 4;
 	pub const MinimumVotingLock: u64 = 5;
-}
-
-thread_local! {
-	static VOTER_BOND: RefCell<u64> = RefCell::new(0);
-	static VOTING_FEE: RefCell<u64> = RefCell::new(0);
-	static PRESENT_SLASH_PER_VOTER: RefCell<u64> = RefCell::new(0);
-	static DECAY_RATIO: RefCell<u32> = RefCell::new(0);
-	static MEMBERS: RefCell<Vec<u64>> = RefCell::new(vec![]);
-}
-
-pub struct VotingBond;
-impl Get<u64> for VotingBond {
-	fn get() -> u64 { VOTER_BOND.with(|v| *v.borrow()) }
-}
-
-pub struct VotingFee;
-impl Get<u64> for VotingFee {
-	fn get() -> u64 { VOTING_FEE.with(|v| *v.borrow()) }
-}
-
-pub struct PresentSlashPerVoter;
-impl Get<u64> for PresentSlashPerVoter {
-	fn get() -> u64 { PRESENT_SLASH_PER_VOTER.with(|v| *v.borrow()) }
-}
-
-pub struct DecayRatio;
-impl Get<u32> for DecayRatio {
-	fn get() -> u32 { DECAY_RATIO.with(|v| *v.borrow()) }
+	pub static VotingBond: u64 = 0;
+	pub static VotingFee: u64 = 0;
+	pub static PresentSlashPerVoter: u64 = 0;
+	pub static DecayRatio: u32 = 0;
+	pub static Members: Vec<u64> = vec![];
 }
 
 pub struct TestChangeMembers;
@@ -175,7 +151,7 @@ pub struct ExtBuilder {
 	decay_ratio: u32,
 	desired_seats: u32,
 	voting_fee: u64,
-	voter_bond: u64,
+	voting_bond: u64,
 	bad_presentation_punishment: u64,
 }
 
@@ -186,7 +162,7 @@ impl Default for ExtBuilder {
 			decay_ratio: 24,
 			desired_seats: 2,
 			voting_fee: 0,
-			voter_bond: 0,
+			voting_bond: 0,
 			bad_presentation_punishment: 1,
 		}
 	}
@@ -209,8 +185,8 @@ impl ExtBuilder {
 		self.bad_presentation_punishment = fee;
 		self
 	}
-	pub fn voter_bond(mut self, fee: u64) -> Self {
-		self.voter_bond = fee;
+	pub fn voting_bond(mut self, fee: u64) -> Self {
+		self.voting_bond = fee;
 		self
 	}
 	pub fn desired_seats(mut self, seats: u32) -> Self {
@@ -218,7 +194,7 @@ impl ExtBuilder {
 		self
 	}
 	pub fn build(self) -> sp_io::TestExternalities {
-		VOTER_BOND.with(|v| *v.borrow_mut() = self.voter_bond);
+		VOTING_BOND.with(|v| *v.borrow_mut() = self.voting_bond);
 		VOTING_FEE.with(|v| *v.borrow_mut() = self.voting_fee);
 		PRESENT_SLASH_PER_VOTER.with(|v| *v.borrow_mut() = self.bad_presentation_punishment);
 		DECAY_RATIO.with(|v| *v.borrow_mut() = self.decay_ratio);
diff --git a/substrate/frame/elections/src/tests.rs b/substrate/frame/elections/src/tests.rs
index 92f6e11252b..d3579ca3374 100644
--- a/substrate/frame/elections/src/tests.rs
+++ b/substrate/frame/elections/src/tests.rs
@@ -298,7 +298,7 @@ fn voting_initial_set_approvals_ignores_voter_index() {
 }
 #[test]
 fn voting_bad_approval_index_slashes_voters_and_bond_reduces_stake() {
-	ExtBuilder::default().voting_fee(5).voter_bond(2).build().execute_with(|| {
+	ExtBuilder::default().voting_fee(5).voting_bond(2).build().execute_with(|| {
 		assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0));
 
 		(1..=63).for_each(|i| vote(i, 0));
@@ -365,7 +365,7 @@ fn voting_cannot_lock_less_than_limit() {
 
 #[test]
 fn voting_locking_more_than_total_balance_is_moot() {
-	ExtBuilder::default().voter_bond(2).build().execute_with(|| {
+	ExtBuilder::default().voting_bond(2).build().execute_with(|| {
 		assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0));
 
 		assert_eq!(balances(&3), (30, 0));
@@ -381,7 +381,7 @@ fn voting_locking_more_than_total_balance_is_moot() {
 
 #[test]
 fn voting_locking_stake_and_reserving_bond_works() {
-	ExtBuilder::default().voter_bond(2).build().execute_with(|| {
+	ExtBuilder::default().voting_bond(2).build().execute_with(|| {
 		assert_ok!(Elections::submit_candidacy(Origin::signed(5), 0));
 
 		assert_eq!(balances(&2), (20, 0));
@@ -558,7 +558,7 @@ fn retracting_inactive_voter_should_work() {
 
 #[test]
 fn retracting_inactive_voter_with_other_candidates_in_slots_should_work() {
-	ExtBuilder::default().voter_bond(2).build().execute_with(|| {
+	ExtBuilder::default().voting_bond(2).build().execute_with(|| {
 		System::set_block_number(4);
 		assert_ok!(Elections::submit_candidacy(Origin::signed(2), 0));
 		assert_ok!(Elections::set_approvals(Origin::signed(2), vec![true], 0, 0, 20));
@@ -1107,7 +1107,7 @@ fn election_present_when_presenter_is_poor_should_not_work() {
 	let test_present = |p| {
 		ExtBuilder::default()
 			.voting_fee(5)
-			.voter_bond(2)
+			.voting_bond(2)
 			.bad_presentation_punishment(p)
 			.build()
 			.execute_with(|| {
@@ -1507,7 +1507,7 @@ fn pot_winning_resets_accumulated_pot() {
 #[test]
 fn pot_resubmitting_approvals_stores_pot() {
 	ExtBuilder::default()
-		.voter_bond(0)
+		.voting_bond(0)
 		.voting_fee(0)
 		.balance_factor(10)
 		.build()
diff --git a/substrate/frame/membership/src/lib.rs b/substrate/frame/membership/src/lib.rs
index 492fda88dd1..06188c42b21 100644
--- a/substrate/frame/membership/src/lib.rs
+++ b/substrate/frame/membership/src/lib.rs
@@ -278,7 +278,6 @@ impl<T: Trait<I>, I: Instance> Contains<T::AccountId> for Module<T, I> {
 mod tests {
 	use super::*;
 
-	use std::cell::RefCell;
 	use frame_support::{
 		assert_ok, assert_noop, impl_outer_origin, parameter_types, weights::Weight,
 		ord_parameter_types
@@ -298,6 +297,8 @@ mod tests {
 		pub const MaximumBlockWeight: Weight = 1024;
 		pub const MaximumBlockLength: u32 = 2 * 1024;
 		pub const AvailableBlockRatio: Perbill = Perbill::one();
+		pub static Members: Vec<u64> = vec![];
+		pub static Prime: Option<u64> = None;
 	}
 	impl frame_system::Trait for Test {
 		type BaseCallFilter = ();
@@ -334,11 +335,6 @@ mod tests {
 		pub const Five: u64 = 5;
 	}
 
-	thread_local! {
-		static MEMBERS: RefCell<Vec<u64>> = RefCell::new(vec![]);
-		static PRIME: RefCell<Option<u64>> = RefCell::new(None);
-	}
-
 	pub struct TestChangeMembers;
 	impl ChangeMembers<u64> for TestChangeMembers {
 		fn change_members_sorted(incoming: &[u64], outgoing: &[u64], new: &[u64]) {
diff --git a/substrate/frame/staking/src/mock.rs b/substrate/frame/staking/src/mock.rs
index 055ebb97308..3aa3e9ae03d 100644
--- a/substrate/frame/staking/src/mock.rs
+++ b/substrate/frame/staking/src/mock.rs
@@ -47,12 +47,6 @@ pub(crate) type Balance = u128;
 
 thread_local! {
 	static SESSION: RefCell<(Vec<AccountId>, HashSet<AccountId>)> = RefCell::new(Default::default());
-	static SESSION_PER_ERA: RefCell<SessionIndex> = RefCell::new(3);
-	static EXISTENTIAL_DEPOSIT: RefCell<Balance> = RefCell::new(0);
-	static SLASH_DEFER_DURATION: RefCell<EraIndex> = RefCell::new(0);
-	static ELECTION_LOOKAHEAD: RefCell<BlockNumber> = RefCell::new(0);
-	static PERIOD: RefCell<BlockNumber> = RefCell::new(1);
-	static MAX_ITERATIONS: RefCell<u32> = RefCell::new(0);
 }
 
 /// Another session handler struct to test on_disabled.
@@ -92,53 +86,6 @@ pub fn is_disabled(controller: AccountId) -> bool {
 	SESSION.with(|d| d.borrow().1.contains(&stash))
 }
 
-pub struct ExistentialDeposit;
-impl Get<Balance> for ExistentialDeposit {
-	fn get() -> Balance {
-		EXISTENTIAL_DEPOSIT.with(|v| *v.borrow())
-	}
-}
-
-pub struct SessionsPerEra;
-impl Get<SessionIndex> for SessionsPerEra {
-	fn get() -> SessionIndex {
-		SESSION_PER_ERA.with(|v| *v.borrow())
-	}
-}
-impl Get<BlockNumber> for SessionsPerEra {
-	fn get() -> BlockNumber {
-		SESSION_PER_ERA.with(|v| *v.borrow() as BlockNumber)
-	}
-}
-
-pub struct ElectionLookahead;
-impl Get<BlockNumber> for ElectionLookahead {
-	fn get() -> BlockNumber {
-		ELECTION_LOOKAHEAD.with(|v| *v.borrow())
-	}
-}
-
-pub struct Period;
-impl Get<BlockNumber> for Period {
-	fn get() -> BlockNumber {
-		PERIOD.with(|v| *v.borrow())
-	}
-}
-
-pub struct SlashDeferDuration;
-impl Get<EraIndex> for SlashDeferDuration {
-	fn get() -> EraIndex {
-		SLASH_DEFER_DURATION.with(|v| *v.borrow())
-	}
-}
-
-pub struct MaxIterations;
-impl Get<u32> for MaxIterations {
-	fn get() -> u32 {
-		MAX_ITERATIONS.with(|v| *v.borrow())
-	}
-}
-
 impl_outer_origin! {
 	pub enum Origin for Test where system = frame_system {}
 }
@@ -186,7 +133,14 @@ parameter_types! {
 	pub const MaximumBlockLength: u32 = 2 * 1024;
 	pub const AvailableBlockRatio: Perbill = Perbill::one();
 	pub const MaxLocks: u32 = 1024;
+	pub static SessionsPerEra: SessionIndex = 3;
+	pub static ExistentialDeposit: Balance = 0;
+	pub static SlashDeferDuration: EraIndex = 0;
+	pub static ElectionLookahead: BlockNumber = 0;
+	pub static Period: BlockNumber = 1;
+	pub static MaxIterations: u32 = 0;
 }
+
 impl frame_system::Trait for Test {
 	type BaseCallFilter = ();
 	type Origin = Origin;
@@ -437,7 +391,7 @@ impl ExtBuilder {
 	pub fn set_associated_constants(&self) {
 		EXISTENTIAL_DEPOSIT.with(|v| *v.borrow_mut() = self.existential_deposit);
 		SLASH_DEFER_DURATION.with(|v| *v.borrow_mut() = self.slash_defer_duration);
-		SESSION_PER_ERA.with(|v| *v.borrow_mut() = self.session_per_era);
+		SESSIONS_PER_ERA.with(|v| *v.borrow_mut() = self.session_per_era);
 		ELECTION_LOOKAHEAD.with(|v| *v.borrow_mut() = self.election_lookahead);
 		PERIOD.with(|v| *v.borrow_mut() = self.session_length);
 		MAX_ITERATIONS.with(|v| *v.borrow_mut() = self.max_offchain_iterations);
diff --git a/substrate/frame/support/src/lib.rs b/substrate/frame/support/src/lib.rs
index a132b787fd9..5dd452dbbe7 100644
--- a/substrate/frame/support/src/lib.rs
+++ b/substrate/frame/support/src/lib.rs
@@ -85,21 +85,27 @@ pub enum Never {}
 
 /// Create new implementations of the [`Get`](crate::traits::Get) trait.
 ///
-/// The so-called parameter type can be created in three different ways:
+/// The so-called parameter type can be created in four different ways:
 ///
-/// - Using `const` to create a parameter type that provides a `const` getter.
-///   It is required that the `value` is const.
+/// - Using `const` to create a parameter type that provides a `const` getter. It is required that
+///   the `value` is const.
 ///
 /// - Declare the parameter type without `const` to have more freedom when creating the value.
 ///
-/// - Using `storage` to create a storage parameter type. This type is special as it tries to
-///   load the value from the storage under a fixed key. If the value could not be found in the
-///   storage, the given default value will be returned. It is required that the value implements
-///   [`Encode`](codec::Encode) and [`Decode`](codec::Decode). The key for looking up the value
-///   in the storage is built using the following formular:
+/// - Using `storage` to create a storage parameter type. This type is special as it tries to load
+///   the value from the storage under a fixed key. If the value could not be found in the storage,
+///   the given default value will be returned. It is required that the value implements
+///   [`Encode`](codec::Encode) and [`Decode`](codec::Decode). The key for looking up the value in
+///   the storage is built using the following formula:
 ///
 ///   `twox_128(":" ++ NAME ++ ":")` where `NAME` is the name that is passed as type name.
 ///
+/// - Using `static` to create a static parameter type. Its value is
+///   being provided by a static variable with the equivalent name in `UPPER_SNAKE_CASE`. An
+///   additional `set` function is provided in this case to alter the static variable. 
+///
+/// **This is intended for testing ONLY and is ONLY available when `std` is enabled**
+///
 /// # Examples
 ///
 /// ```
@@ -114,12 +120,14 @@ pub enum Never {}
 ///    /// Visibility of the type is optional
 ///    OtherArgument: u64 = non_const_expression();
 ///    pub storage StorageArgument: u64 = 5;
+///    pub static StaticArgument: u32 = 7;
 /// }
 ///
 /// trait Config {
 ///    type Parameter: Get<u64>;
 ///    type OtherParameter: Get<u64>;
 ///    type StorageParameter: Get<u64>;
+///    type StaticParameter: Get<u32>;
 /// }
 ///
 /// struct Runtime;
@@ -127,7 +135,10 @@ pub enum Never {}
 ///    type Parameter = Argument;
 ///    type OtherParameter = OtherArgument;
 ///    type StorageParameter = StorageArgument;
+///    type StaticParameter = StaticArgument;
 /// }
+///
+/// // In testing, `StaticArgument` can be altered later: `StaticArgument::set(8)`.
 /// ```
 ///
 /// # Invalid example:
@@ -142,7 +153,6 @@ pub enum Never {}
 ///    pub const Argument: u64 = non_const_expression();
 /// }
 /// ```
-
 #[macro_export]
 macro_rules! parameter_types {
 	(
@@ -235,7 +245,69 @@ macro_rules! parameter_types {
 				I::from(Self::get())
 			}
 		}
-	}
+	};
+	(
+		$(
+			$( #[ $attr:meta ] )*
+			$vis:vis static $name:ident: $type:ty = $value:expr;
+		)*
+	) => (
+		$crate::parameter_types_impl_thread_local!(
+			$(
+				$( #[ $attr ] )*
+				$vis static $name: $type = $value;
+			)*
+		);
+	);
+}
+
+#[cfg(not(feature = "std"))]
+#[macro_export]
+macro_rules! parameter_types_impl_thread_local {
+	( $( $any:tt )* ) => {
+		compile_error!("static parameter types is only available in std and for testing.");
+	};
+}
+
+#[cfg(feature = "std")]
+#[macro_export]
+macro_rules! parameter_types_impl_thread_local {
+	(
+		$(
+			$( #[ $attr:meta ] )*
+			$vis:vis static $name:ident: $type:ty = $value:expr;
+		)*
+	) => {
+		$crate::parameter_types_impl_thread_local!(
+			IMPL_THREAD_LOCAL $( $vis, $name, $type, $value, )*
+		);
+		$crate::paste::item! {
+			$crate::parameter_types!(
+				$(
+					$( #[ $attr ] )*
+					$vis $name: $type = [<$name:snake:upper>].with(|v| v.borrow().clone());
+				)*
+			);
+			$(
+				impl $name {
+					/// Set the internal value.
+					pub fn set(t: $type) {
+						[<$name:snake:upper>].with(|v| *v.borrow_mut() = t);
+					}
+				}
+			)*
+		}
+	};
+	(IMPL_THREAD_LOCAL $( $vis:vis, $name:ident, $type:ty, $value:expr, )* ) => {
+		$crate::paste::item! {
+			thread_local! {
+				$(
+					pub static [<$name:snake:upper>]: std::cell::RefCell<$type> =
+						std::cell::RefCell::new($value);
+				)*
+			}
+		}
+	};
 }
 
 /// Macro for easily creating a new implementation of both the `Get` and `Contains` traits. Use
diff --git a/substrate/frame/transaction-payment/src/lib.rs b/substrate/frame/transaction-payment/src/lib.rs
index dd310c26398..751aa57da0f 100644
--- a/substrate/frame/transaction-payment/src/lib.rs
+++ b/substrate/frame/transaction-payment/src/lib.rs
@@ -571,7 +571,6 @@ mod tests {
 		traits::{BlakeTwo256, IdentityLookup},
 		Perbill,
 	};
-	use std::cell::RefCell;
 	use smallvec::smallvec;
 
 	const CALL: &<Runtime as frame_system::Trait>::Call =
@@ -599,20 +598,14 @@ mod tests {
 		pub enum Origin for Runtime {}
 	}
 
-	thread_local! {
-		static EXTRINSIC_BASE_WEIGHT: RefCell<u64> = RefCell::new(0);
-	}
-
-	pub struct ExtrinsicBaseWeight;
-	impl Get<u64> for ExtrinsicBaseWeight {
-		fn get() -> u64 { EXTRINSIC_BASE_WEIGHT.with(|v| *v.borrow()) }
-	}
-
 	parameter_types! {
 		pub const BlockHashCount: u64 = 250;
 		pub const MaximumBlockWeight: Weight = 1024;
 		pub const MaximumBlockLength: u32 = 2 * 1024;
 		pub const AvailableBlockRatio: Perbill = Perbill::one();
+		pub static ExtrinsicBaseWeight: u64 = 0;
+		pub static TransactionByteFee: u64 = 1;
+		pub static WeightToFee: u64 = 1;
 	}
 
 	impl frame_system::Trait for Runtime {
@@ -656,17 +649,7 @@ mod tests {
 		type MaxLocks = ();
 		type WeightInfo = ();
 	}
-	thread_local! {
-		static TRANSACTION_BYTE_FEE: RefCell<u64> = RefCell::new(1);
-		static WEIGHT_TO_FEE: RefCell<u64> = RefCell::new(1);
-	}
-
-	pub struct TransactionByteFee;
-	impl Get<u64> for TransactionByteFee {
-		fn get() -> u64 { TRANSACTION_BYTE_FEE.with(|v| *v.borrow()) }
-	}
 
-	pub struct WeightToFee;
 	impl WeightToFeePolynomial for WeightToFee {
 		type Balance = u64;
 
diff --git a/substrate/frame/vesting/src/lib.rs b/substrate/frame/vesting/src/lib.rs
index 8b78eac4fed..c09516c2cc2 100644
--- a/substrate/frame/vesting/src/lib.rs
+++ b/substrate/frame/vesting/src/lib.rs
@@ -390,10 +390,8 @@ impl<T: Trait> VestingSchedule<T::AccountId> for Module<T> where
 mod tests {
 	use super::*;
 
-	use std::cell::RefCell;
 	use frame_support::{
 		assert_ok, assert_noop, impl_outer_origin, parameter_types, weights::Weight,
-		traits::Get
 	};
 	use sp_core::H256;
 	use sp_runtime::{
@@ -456,6 +454,7 @@ mod tests {
 	}
 	parameter_types! {
 		pub const MinVestedTransfer: u64 = 256 * 2;
+		pub static ExistentialDeposit: u64 = 0;
 	}
 	impl Trait for Test {
 		type Event = ();
@@ -468,13 +467,6 @@ mod tests {
 	type Balances = pallet_balances::Module<Test>;
 	type Vesting = Module<Test>;
 
-	thread_local! {
-		static EXISTENTIAL_DEPOSIT: RefCell<u64> = RefCell::new(0);
-	}
-	pub struct ExistentialDeposit;
-	impl Get<u64> for ExistentialDeposit {
-		fn get() -> u64 { EXISTENTIAL_DEPOSIT.with(|v| *v.borrow()) }
-	}
 
 	pub struct ExtBuilder {
 		existential_deposit: u64,
-- 
GitLab