1use super::*;
21use crate::{self as bags_list};
22use frame_election_provider_support::VoteWeight;
23use frame_support::{derive_impl, parameter_types};
24use sp_runtime::BuildStorage;
25use std::collections::HashMap;
26
27pub type AccountId = <Runtime as frame_system::Config>::AccountId;
28pub type Balance = u32;
29
30parameter_types! {
31 pub static NextVoteWeightMap: HashMap<AccountId, VoteWeight> = Default::default();
33}
34
35pub struct StakingMock;
36impl ScoreProvider<AccountId> for StakingMock {
37 type Score = VoteWeight;
38
39 fn score(id: &AccountId) -> Option<Self::Score> {
40 NextVoteWeightMap::get().get(id).cloned()
41 }
42
43 frame_election_provider_support::runtime_benchmarks_or_std_enabled! {
44 fn set_score_of(id: &AccountId, weight: Self::Score) {
45 NEXT_VOTE_WEIGHT_MAP.with(|m| m.borrow_mut().insert(*id, weight));
46 }
47 }
48}
49
50#[derive_impl(frame_system::config_preludes::TestDefaultConfig)]
51impl frame_system::Config for Runtime {
52 type Block = Block;
53 type AccountData = pallet_balances::AccountData<Balance>;
54}
55
56parameter_types! {
57 pub static BagThresholds: &'static [VoteWeight] = &[10, 20, 30, 40, 50, 60, 1_000, 2_000, 10_000];
58 pub static AutoRebagNumber: u32 = 10;
59}
60
61impl bags_list::Config for Runtime {
62 type RuntimeEvent = RuntimeEvent;
63 type WeightInfo = ();
64 type ScoreProvider = StakingMock;
65 type BagThresholds = BagThresholds;
66 type MaxAutoRebagPerBlock = AutoRebagNumber;
67 type Score = VoteWeight;
68}
69
70type Block = frame_system::mocking::MockBlock<Runtime>;
71frame_support::construct_runtime!(
72 pub enum Runtime {
73 System: frame_system,
74 BagsList: bags_list,
75 }
76);
77
78pub(crate) const GENESIS_IDS: [(AccountId, VoteWeight); 4] =
80 [(1, 10), (2, 1_000), (3, 1_000), (4, 1_000)];
81
82#[derive(Default)]
83pub struct ExtBuilder {
84 ids: Vec<(AccountId, VoteWeight)>,
85 skip_genesis_ids: bool,
86}
87
88#[cfg(any(feature = "runtime-benchmarks", feature = "fuzz", test))]
89impl ExtBuilder {
90 #[cfg(test)]
92 pub(crate) fn skip_genesis_ids(mut self) -> Self {
93 self.skip_genesis_ids = true;
94 self
95 }
96
97 #[cfg(test)]
99 pub(crate) fn add_ids(mut self, ids: Vec<(AccountId, VoteWeight)>) -> Self {
100 self.ids = ids;
101 self
102 }
103
104 pub(crate) fn build(self) -> sp_io::TestExternalities {
105 sp_tracing::try_init_simple();
106 let storage = frame_system::GenesisConfig::<Runtime>::default().build_storage().unwrap();
107
108 let ids_with_weight: Vec<_> = if self.skip_genesis_ids {
109 self.ids.iter().collect()
110 } else {
111 GENESIS_IDS.iter().chain(self.ids.iter()).collect()
112 };
113
114 let mut ext = sp_io::TestExternalities::from(storage);
115 ext.execute_with(|| {
116 for (id, weight) in ids_with_weight {
117 frame_support::assert_ok!(List::<Runtime>::insert(*id, *weight));
118 StakingMock::set_score_of(id, *weight);
119 }
120 });
121
122 ext
123 }
124
125 pub fn build_and_execute(self, test: impl FnOnce() -> ()) {
126 self.build().execute_with(|| {
127 test();
128 List::<Runtime>::do_try_state().expect("do_try_state post condition failed")
129 })
130 }
131
132 #[cfg(test)]
133 pub(crate) fn build_and_execute_no_post_check(self, test: impl FnOnce() -> ()) {
134 self.build().execute_with(test)
135 }
136}
137
138#[cfg(test)]
139pub(crate) mod test_utils {
140 use super::*;
141 use list::Bag;
142
143 pub(crate) fn bag_as_ids(bag: &Bag<Runtime>) -> Vec<AccountId> {
145 bag.iter().map(|n| *n.id()).collect::<Vec<_>>()
146 }
147
148 pub(crate) fn get_list_as_ids() -> Vec<AccountId> {
150 List::<Runtime>::iter().map(|n| *n.id()).collect::<Vec<_>>()
151 }
152}