Select Git revision
-
Cédric Moreau authoredCédric Moreau authored
iterative.rs 26.65 KiB
use crate::common::golden_testing::assert::compare_with_storage;
use crate::common::golden_testing::checker::{Checker, StorageCheck};
use crate::common::golden_testing::key::Key;
use crate::common::golden_testing::key::KeyName;
use crate::common::golden_testing::runtime::extract_storage_entries_normalized;
use crate::common::{get_account_id_from_seed, get_authority_keys_from_seed, get_from_seed};
use codec::{Decode, Error};
use common_runtime::entities::IdtyData;
use frame_support::metadata::{RuntimeMetadata, StorageEntryType};
use frame_support::storage::storage_prefix;
use gdev_runtime::opaque::SessionKeys;
use gdev_runtime::Runtime;
use maplit::btreemap;
use pallet_identity::{IdtyStatus, IdtyValue};
use pallet_universal_dividend::FirstEligibleUd;
use pretty_assertions::assert_eq;
use scale_info::form::PortableForm;
use sp_api::{AsTrieBackend, StateBackend};
use sp_consensus_babe::{AuthorityId, BabeAuthorityWeight};
use sp_core::bounded::WeakBoundedVec;
use sp_core::{map, sr25519};
use sp_io::TestExternalities;
use sp_runtime::RuntimeString;
use std::collections::HashMap;
use std::fmt::{format, Debug};
use std::fs::metadata;
use std::iter::Map;
use std::ops::Add;
use std::str::FromStr;
/// A struct to ease the testing of extrinsics' impact on the Storage, using the following techniques:
///
/// - always check *all keys and values of the current state in the Storage* (`test_storage()`)
/// - first define a starting state (`new()` or `new_default()`)
/// - then onyl specify the changed values to acknowledge the changes to make test pass (`change_expected()`)
///
/// Useful for extrinsic testing where we start from a known Storage state, and just want to check
/// the differences after we applied some extrinsics.
pub struct StorageIterativeChecker {
expected_storage: fn() -> Vec<Key>,
overriden: HashMap<KeyName, Box<dyn Fn() -> Key>>,
mergeable: HashMap<KeyName, Option<Box<dyn Fn() -> Key>>>,
get_metadata: fn() -> RuntimeMetadata,
}
impl StorageIterativeChecker {
pub fn change_expected(&mut self, k: Box<dyn Fn() -> Key>) {
if false && (k() as Key).is_mergeable() {
self.mergeable.insert(k().name(), Some(k));
} else {
self.overriden.insert(k().name(), k);
}
}
}
impl StorageIterativeChecker {
pub fn new(
initial_values: fn() -> Vec<Key>,
get_metadata: fn() -> RuntimeMetadata,
) -> StorageIterativeChecker {
StorageIterativeChecker {
expected_storage: initial_values,
overriden: HashMap::new(),
mergeable: HashMap::new(),
get_metadata,
}
}
pub fn new_default(get_metadata: fn() -> RuntimeMetadata) -> StorageIterativeChecker {
StorageIterativeChecker {
expected_storage: || {
vec![
Key::SystemNumber(2),
Key::SystemParentHash(
sp_core::H256::from_str(
"0x4545454545454545454545454545454545454545454545454545454545454545",
)
.unwrap(),
),
Key::SystemLastRuntimeUpgrade(frame_system::LastRuntimeUpgradeInfo {
spec_name: RuntimeString::Owned("gdev".to_string()),
spec_version: codec::Compact::from(400u32),
}),
Key::SystemUpgradedToU32RefCount(1),
Key::SystemUpgradedToTripleRefCount(1),
Key::UniversalDividendCurrentUd(1000),
Key::UniversalDividendMonetaryMass(0),
Key::UniversalDividendNextReeval(100),
Key::UniversalDividendPastReevals(4),
Key::_ManualKey(
"Identity".to_string(),
"IdentitiesNames".to_string(),
"[
\"Alice\" = ()
\"Bob\" = ()
\"Charlie\" = ()
\"Dave\" = ()
]"
.to_string(),
),
Key::IdentityIdentities(btreemap!(
1 => IdtyValue {
data: IdtyData {
first_eligible_ud: FirstEligibleUd::from(1),
},
next_creatable_identity_on: 0,
old_owner_key: None,
owner_key: get_account_id_from_seed::<sr25519::Public>("Alice"),
removable_on: 0,
status: IdtyStatus::Validated,
},
2 => IdtyValue {
data: IdtyData {
first_eligible_ud: FirstEligibleUd::from(1),
},
next_creatable_identity_on: 0,
old_owner_key: None,
owner_key: get_account_id_from_seed::<sr25519::Public>("Bob"),
removable_on: 0,
status: IdtyStatus::Validated,
},
3 => IdtyValue {
data: IdtyData {
first_eligible_ud: FirstEligibleUd::from(1),
},
next_creatable_identity_on: 0,
old_owner_key: None,
owner_key: get_account_id_from_seed::<sr25519::Public>("Charlie"),
removable_on: 0,
status: IdtyStatus::Validated,
},
4 => IdtyValue {
data: IdtyData {
first_eligible_ud: FirstEligibleUd::from(1),
},
next_creatable_identity_on: 0,
old_owner_key: None,
owner_key: get_account_id_from_seed::<sr25519::Public>("Dave"),
removable_on: 0,
status: IdtyStatus::Validated,
}
)),
Key::IdentityCounterForIdentities(4),
Key::IdentityNextIdtyIndex(5),
Key::MembershipCounterForMembership(4),
Key::SmithMembershipCounterForMembership(3),
Key::ProvideRandomnessNexEpochHookIn(5),
Key::BabeInitialized(0),
Key::BabeAuthorities(
WeakBoundedVec::try_from(vec![(
get_from_seed::<AuthorityId>("Alice"),
1u64,
)])
.unwrap(),
),
Key::BabeNextAuthorities(
WeakBoundedVec::try_from(vec![(
get_from_seed::<AuthorityId>("Alice"),
1u64,
)])
.unwrap(),
),
Key::ParametersParametersStorage(
pallet_duniter_test_parameters::types::Parameters::<u32, u32, u64> {
babe_epoch_duration: 25,
cert_period: 15,
cert_max_by_issuer: 10,
cert_min_received_cert_to_issue_cert: 2,
cert_validity_period: 10000,
idty_confirm_period: 40,
idty_creation_period: 50,
membership_period: 100,
pending_membership_period: 500,
ud_creation_period: 10,
ud_reeval_period: 200,
smith_cert_period: 15,
smith_cert_max_by_issuer: 8,
smith_cert_min_received_cert_to_issue_cert: 2,
smith_cert_validity_period: 1000,
smith_membership_period: 1000,
smith_pending_membership_period: 500,
smith_wot_first_cert_issuable_on: 20,
smith_wot_min_cert_for_membership: 2,
wot_first_cert_issuable_on: 20,
wot_min_cert_for_create_idty_right: 2,
wot_min_cert_for_membership: 2,
},
),
Key::AuthorityMembersAuthoritiesCounter(1),
Key::AuthorityMembersOnlineAuthorities(vec![1u32]),
Key::SessionValidators(vec![get_authority_keys_from_seed("Alice").0]),
Key::SessionQueuedKeys(vec![(
get_authority_keys_from_seed("Alice").0,
SessionKeys {
grandpa: get_authority_keys_from_seed("Alice").2,
babe: get_authority_keys_from_seed("Alice").1,
im_online: get_authority_keys_from_seed("Alice").3,
authority_discovery: get_authority_keys_from_seed("Alice").4,
},
)]),
Key::TransactionPaymentNextFeeMultiplier(0),
Key::AuthorshipUncles(0),
Key::AuthorshipDidSetUncles(0),
Key::ImOnlineKeys(
WeakBoundedVec::try_from(vec![get_authority_keys_from_seed("Alice").3])
.unwrap(),
),
Key::_ManualKey("System".to_string(), "Account".to_string(), "[
306721211d5404bd9da88e0204360a1a9ab8b87c66c1bc2fcdd37f3c2222cc20 (5DAAnrj7...) = AccountInfo { nonce: 0, consumers: 0, providers: 0, sufficients: 1, data: AccountData { random_id: Some(0x0303030303030303030303030303030303030303030303030303030303030303), free: 0, reserved: 0, fee_frozen: 0 } }
6d6f646c70792f74727372790000000000000000000000000000000000000000 (5EYCAe5i...) = AccountInfo { nonce: 0, consumers: 0, providers: 1, sufficients: 0, data: AccountData { random_id: None, free: 200, reserved: 0, fee_frozen: 0 } }
8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48 (5FHneW46...) = AccountInfo { nonce: 0, consumers: 0, providers: 1, sufficients: 1, data: AccountData { random_id: Some(0x0101010101010101010101010101010101010101010101010101010101010101), free: 0, reserved: 0, fee_frozen: 0 } }
90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22 (5FLSigC9...) = AccountInfo { nonce: 0, consumers: 0, providers: 1, sufficients: 1, data: AccountData { random_id: Some(0x0202020202020202020202020202020202020202020202020202020202020202), free: 0, reserved: 0, fee_frozen: 0 } }
d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d (5GrwvaEF...) = AccountInfo { nonce: 0, consumers: 0, providers: 1, sufficients: 1, data: AccountData { random_id: Some(0x0000000000000000000000000000000000000000000000000000000000000000), free: 0, reserved: 0, fee_frozen: 0 } }
]".to_string()),
Key::_ManualKey("System".to_string(), "BlockHash".to_string(), "[
0 = 0x4545454545454545454545454545454545454545454545454545454545454545
]".to_string()),
Key::_ManualKey("Identity".to_string(), "IdentityIndexOf".to_string(), "[
306721211d5404bd9da88e0204360a1a9ab8b87c66c1bc2fcdd37f3c2222cc20 (5DAAnrj7...) = 4
8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48 (5FHneW46...) = 2
90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22 (5FLSigC9...) = 3
d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d (5GrwvaEF...) = 1
]".to_string()),
Key::_ManualKey("Scheduler".to_string(), "Agenda".to_string(), "[
]".to_string()),
Key::_ManualKey("Balances".to_string(), "Account".to_string(), "[
]".to_string()),
Key::_ManualKey("Balances".to_string(), "Locks".to_string(), "[
]".to_string()),
Key::_ManualKey("Balances".to_string(), "Reserves".to_string(), "[
]".to_string()),
Key::_ManualKey("OneshotAccount".to_string(), "OneshotAccounts".to_string(), "[
]".to_string()),
Key::_ManualKey("AuthorityMembers".to_string(), "AccountIdOf".to_string(), "[
]".to_string()),
Key::_ManualKey("AuthorityMembers".to_string(), "Members".to_string(), "[
1 = MemberData { expire_on_session: 0, must_rotate_keys_before: 1500, owner_key: d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d (5GrwvaEF...) }
2 = MemberData { expire_on_session: 0, must_rotate_keys_before: 1500, owner_key: 8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48 (5FHneW46...) }
3 = MemberData { expire_on_session: 0, must_rotate_keys_before: 1500, owner_key: 90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22 (5FLSigC9...) }
]".to_string()),
// TODO: curious that this is empty on current GDev
Key::_ManualKey("AuthorityMembers".to_string(), "MustRotateKeysBefore".to_string(), "[
1500 = [1]
]".to_string()),
Key::_ManualKey("Offences".to_string(), "Reports".to_string(), "[
]".to_string()),
Key::_ManualKey("Session".to_string(), "NextKeys".to_string(), "[
8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48 (5FHneW46...) = SessionKeys { grandpa: Public(d17c2d7823ebf260fd138f2d7e27d114c0145d968b5ff5006125f2414fadae69 (5GoNkf6W...)), babe: Public(8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48 (5FHneW46...)), im_online: Public(8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48 (5FHneW46...)), authority_discovery: Public(8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48 (5FHneW46...)) }
90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22 (5FLSigC9...) = SessionKeys { grandpa: Public(439660b36c6c03afafca027b910b4fecf99801834c62a5e6006f27d978de234f (5DbKjhNL...)), babe: Public(90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22 (5FLSigC9...)), im_online: Public(90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22 (5FLSigC9...)), authority_discovery: Public(90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22 (5FLSigC9...)) }
d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d (5GrwvaEF...) = SessionKeys { grandpa: Public(88dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee (5FA9nQDV...)), babe: Public(d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d (5GrwvaEF...)), im_online: Public(d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d (5GrwvaEF...)), authority_discovery: Public(d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d (5GrwvaEF...)) }
]".to_string()),
Key::_ManualKey("Session".to_string(), "KeyOwner".to_string(), "[
(KeyTypeId([103, 114, 97, 110]), [136, 220, 52, 23, 213, 5, 142, 196, 180, 80, 62, 12, 18, 234, 26, 10, 137, 190, 32, 15, 233, 137, 34, 66, 61, 67, 52, 1, 79, 166, 176, 238]) = d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d (5GrwvaEF...)
(KeyTypeId([103, 114, 97, 110]), [209, 124, 45, 120, 35, 235, 242, 96, 253, 19, 143, 45, 126, 39, 209, 20, 192, 20, 93, 150, 139, 95, 245, 0, 97, 37, 242, 65, 79, 173, 174, 105]) = 8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48 (5FHneW46...)
(KeyTypeId([103, 114, 97, 110]), [67, 150, 96, 179, 108, 108, 3, 175, 175, 202, 2, 123, 145, 11, 79, 236, 249, 152, 1, 131, 76, 98, 165, 230, 0, 111, 39, 217, 120, 222, 35, 79]) = 90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22 (5FLSigC9...)
(KeyTypeId([105, 109, 111, 110]), [142, 175, 4, 21, 22, 135, 115, 99, 38, 201, 254, 161, 126, 37, 252, 82, 135, 97, 54, 147, 201, 18, 144, 156, 178, 38, 170, 71, 148, 242, 106, 72]) = 8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48 (5FHneW46...)
(KeyTypeId([105, 109, 111, 110]), [144, 181, 171, 32, 92, 105, 116, 201, 234, 132, 27, 230, 136, 134, 70, 51, 220, 156, 168, 163, 87, 132, 62, 234, 207, 35, 20, 100, 153, 101, 254, 34]) = 90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22 (5FLSigC9...)
(KeyTypeId([105, 109, 111, 110]), [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125]) = d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d (5GrwvaEF...)
(KeyTypeId([97, 117, 100, 105]), [142, 175, 4, 21, 22, 135, 115, 99, 38, 201, 254, 161, 126, 37, 252, 82, 135, 97, 54, 147, 201, 18, 144, 156, 178, 38, 170, 71, 148, 242, 106, 72]) = 8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48 (5FHneW46...)
(KeyTypeId([97, 117, 100, 105]), [144, 181, 171, 32, 92, 105, 116, 201, 234, 132, 27, 230, 136, 134, 70, 51, 220, 156, 168, 163, 87, 132, 62, 234, 207, 35, 20, 100, 153, 101, 254, 34]) = 90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22 (5FLSigC9...)
(KeyTypeId([97, 117, 100, 105]), [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125]) = d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d (5GrwvaEF...)
(KeyTypeId([98, 97, 98, 101]), [142, 175, 4, 21, 22, 135, 115, 99, 38, 201, 254, 161, 126, 37, 252, 82, 135, 97, 54, 147, 201, 18, 144, 156, 178, 38, 170, 71, 148, 242, 106, 72]) = 8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48 (5FHneW46...)
(KeyTypeId([98, 97, 98, 101]), [144, 181, 171, 32, 92, 105, 116, 201, 234, 132, 27, 230, 136, 134, 70, 51, 220, 156, 168, 163, 87, 132, 62, 234, 207, 35, 20, 100, 153, 101, 254, 34]) = 90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22 (5FLSigC9...)
(KeyTypeId([98, 97, 98, 101]), [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125]) = d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d (5GrwvaEF...)
]".to_string()),
Key::_ManualKey("TechnicalCommittee".to_string(), "ProposalOf".to_string(), "[
]".to_string()),
Key::_ManualKey("TechnicalCommittee".to_string(), "Voting".to_string(), "[
]".to_string()),
Key::_ManualKey("Identity".to_string(), "IdentitiesRemovableOn".to_string(), "[
]".to_string()),
Key::_ManualKey("Membership".to_string(), "Membership".to_string(), "[
1 = MembershipData { expire_on: 100 }
2 = MembershipData { expire_on: 100 }
3 = MembershipData { expire_on: 100 }
4 = MembershipData { expire_on: 100 }
]".to_string()),
Key::_ManualKey("Membership".to_string(), "MembershipsExpireOn".to_string(), "[
100 = [1, 2, 3, 4]
]".to_string()),
Key::_ManualKey("Membership".to_string(), "PendingMembership".to_string(), "[
]".to_string()),
Key::_ManualKey("Membership".to_string(), "PendingMembershipsExpireOn".to_string(), "[
]".to_string()),
Key::_ManualKey("Cert".to_string(), "CertsByReceiver".to_string(), "[
1 = [(2, 10000), (3, 10000), (4, 10000)]
2 = [(1, 10000), (3, 10000), (4, 10000)]
3 = [(1, 10000), (2, 10000), (4, 10000)]
4 = [(1, 10000), (2, 10000), (3, 10000)]
]".to_string()),
Key::_ManualKey("Cert".to_string(), "StorageCertsRemovableOn".to_string(), "[
10000 = [(2, 1), (3, 1), (4, 1), (1, 2), (3, 2), (4, 2), (1, 3), (2, 3), (4, 3), (1, 4), (2, 4), (3, 4)]
]".to_string()),
Key::_ManualKey("SmithMembership".to_string(), "Membership".to_string(), "[
1 = MembershipData { expire_on: 1000 }
2 = MembershipData { expire_on: 1000 }
3 = MembershipData { expire_on: 1000 }
]".to_string()),
Key::_ManualKey("SmithMembership".to_string(), "MembershipsExpireOn".to_string(), "[
1000 = [1, 2, 3]
]".to_string()),
Key::_ManualKey("SmithMembership".to_string(), "PendingMembership".to_string(), "[
]".to_string()),
Key::_ManualKey("SmithMembership".to_string(), "PendingMembershipsExpireOn".to_string(), "[
]".to_string()),
Key::_ManualKey("SmithCert".to_string(), "StorageCertsRemovableOn".to_string(), "[
1000 = [(2, 1), (3, 1), (1, 2), (3, 2), (1, 3), (2, 3)]
]".to_string()),
Key::_ManualKey("ProvideRandomness".to_string(), "RequestsReadyAtEpoch".to_string(), "[
]".to_string()),
Key::_ManualKey("ProvideRandomness".to_string(), "RequestsIds".to_string(), "[
]".to_string()),
Key::_ManualKey("Proxy".to_string(), "Proxies".to_string(), "[
]".to_string()),
Key::_ManualKey("Proxy".to_string(), "Announcements".to_string(), "[
]".to_string()),
Key::_ManualKey("Treasury".to_string(), "Proposals".to_string(), "[
]".to_string()),
Key::_ManualKey("Offences".to_string(), "ConcurrentReportsIndex".to_string(), "[
]".to_string()),
Key::_ManualKey("Multisig".to_string(), "Multisigs".to_string(), "[
]".to_string()),
Key::_ManualKey("AtomicSwap".to_string(), "PendingSwaps".to_string(), "[
]".to_string()),
Key::_ManualKey("Grandpa".to_string(), "SetIdSession".to_string(), "[
0 = 0
]".to_string()),
Key::_ManualKey("Cert".to_string(), "StorageIdtyCertMeta".to_string(), "[
1 = IdtyCertMeta { issued_count: 3, next_issuable_on: 0, received_count: 3 }
2 = IdtyCertMeta { issued_count: 3, next_issuable_on: 0, received_count: 3 }
3 = IdtyCertMeta { issued_count: 3, next_issuable_on: 0, received_count: 3 }
4 = IdtyCertMeta { issued_count: 3, next_issuable_on: 0, received_count: 3 }
]".to_string()),
Key::_ManualKey("SmithCert".to_string(), "StorageIdtyCertMeta".to_string(), "[
1 = IdtyCertMeta { issued_count: 2, next_issuable_on: 0, received_count: 2 }
2 = IdtyCertMeta { issued_count: 2, next_issuable_on: 0, received_count: 2 }
3 = IdtyCertMeta { issued_count: 2, next_issuable_on: 0, received_count: 2 }
]".to_string()),
]
},
overriden: HashMap::new(),
mergeable: HashMap::new(),
get_metadata,
}
}
/// Test our currently expected state against the real state in the Storage.
/// **Must be tested under an externalities-provided environment.**
/// `expected_keys_count` is the number of storage items that we expect to find in the Runtime.
pub fn test_storage(&self, expected_keys_count: u32) {
let mut expected = self.get_expected_state();
expect_storage(self.get_metadata, &mut expected, expected_keys_count);
println!("----------------------")
}
/// Test static keys of Substrate
pub fn test_well_known_keys(&self, externalities: &mut TestExternalities) {
let binding = externalities.as_backend();
let backend = binding.as_trie_backend();
let keys_in_trie = backend.keys(&[]);
let mut well_known: Vec<String> = vec![];
for x in &keys_in_trie {
if let Ok(v) = String::from_utf8(x.clone()) {
well_known.push(format!("{}", v));
}
}
assert_eq!(well_known[0], ":code");
assert_eq!(well_known[1], ":extrinsic_index");
assert_eq!(well_known[2], ":grandpa_authorities");
assert_eq!(well_known.len(), 3);
}
/// Constructs the expectations vector.
fn get_expected_state(&self) -> Vec<Box<dyn StorageCheck>> {
let mut map: HashMap<KeyName, Box<dyn StorageCheck>> = HashMap::new();
// Set the initially expected values
for e in (self.expected_storage)() {
let name = e.name().clone();
let check: Option<Box<dyn StorageCheck>> = Some(e.to_check());
if let Some(c) = check {
map.insert(name, c);
}
}
// Override these values eventually
self.overriden.iter().for_each(|(k, v)| {
let v: Key = v();
if v.is_mergeable() {
if let Some(e) = (self.expected_storage)()
.into_iter()
.find(|k| k.name() == v.name())
{
let merged = e.merge_into(v);
map.insert(k.clone(), merged.to_check());
} else {
map.insert(k.clone(), v.to_check());
}
} else {
map.insert(k.clone(), v.to_check());
}
});
map.into_values().collect()
}
}
/// Explores the Runtime to retrive all storage entries (pallet.storage_name) and compare the values
/// against our expected values in golden testing format.
fn expect_storage(
get_metadata: fn() -> RuntimeMetadata,
tested: &mut Vec<Box<dyn StorageCheck>>,
expected_keys_count: u32,
) {
// Golden testing part
let meta = get_metadata();
let mut entries_count = 0u32;
// Explore the Runtime to fetch the storage entries
extract_storage_entries_normalized(&meta)
.unwrap()
.iter()
.for_each(|se| {
entries_count = entries_count.add(1);
let e = format!("{}.{}", se.pallet_name, se.storage_name);
// What is not explicitely tested but for which a storage key exist is considered
// like a test of absence. So if the Storage has a value, we will get a golden comparison error.
if let None = tested.iter_mut().find(|t| t.to_dotted_form() == e) {
if let StorageEntryType::Map { .. } = se.metadata.clone().ty {
if let Ok(key) = Key::try_from(e.clone()) {
// Specific
let mut c = key.to_check();
tested.push(c);
} else {
// panic!("{}{} must implement TryFrom", se.pallet_name.as_str(), se.storage_name.as_str());
println!(
"{}{} must implement TryFrom",
se.pallet_name.as_str(),
se.storage_name.as_str()
);
// TODO: do not allow try_from to fail
tested.push(Checker::absent(
se.pallet_name.as_str(),
se.storage_name.as_str(),
"<absent>",
None,
));
}
} else {
tested.push(Checker::absent(
se.pallet_name.as_str(),
se.storage_name.as_str(),
"<absent>",
None,
));
}
}
});
// The golden comparison
compare_with_storage(&tested);
// Check the quantities
assert_eq!(expected_keys_count, entries_count);
assert_eq!(expected_keys_count, tested.len() as u32);
}