Skip to content
Snippets Groups Projects
Select Git revision
  • 2bdf2412efdb3b132d0aa2610843fccf16f56d0f
  • master default protected
  • 313_ci_image
  • 311_gtest_fixes
  • set_UniversalDividendApi_in_RuntimeApiCollection
  • tuxmain/fix-change-owner-key
  • network/gtest-1000 protected
  • upgradable-multisig
  • runtime/gtest-1000
  • network/gdev-800 protected
  • cgeek/issue-297-cpu
  • gdev-800-tests
  • update-docker-compose-rpc-squid-names
  • fix-252
  • 1000i100-test
  • hugo/tmp-0.9.1
  • network/gdev-803 protected
  • hugo/endpoint-gossip
  • network/gdev-802 protected
  • hugo/distance-precompute
  • network/gdev-900 protected
  • gtest-1000-0.11.1 protected
  • gtest-1000-0.11.0 protected
  • gtest-1000 protected
  • gdev-900-0.10.1 protected
  • gdev-900-0.10.0 protected
  • gdev-900-0.9.2 protected
  • gdev-800-0.8.0 protected
  • gdev-900-0.9.1 protected
  • gdev-900-0.9.0 protected
  • gdev-803 protected
  • gdev-802 protected
  • runtime-801 protected
  • gdev-800 protected
  • runtime-800-bis protected
  • runtime-800 protected
  • runtime-800-backup protected
  • runtime-701 protected
  • runtime-700 protected
  • runtime-600 protected
  • runtime-500 protected
41 results

command.rs

Blame
  • 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);
    }