// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // Substrate is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . #[cfg(test)] // Do not complain about unused `dispatch` and `dispatch_aux`. #[allow(dead_code)] mod tests { use frame_support::metadata::*; use sp_io::TestExternalities; use std::marker::PhantomData; use codec::{Encode, Decode, EncodeLike}; frame_support::decl_module! { pub struct Module for enum Call where origin: T::Origin {} } pub trait Trait { type Origin: Encode + Decode + EncodeLike + std::default::Default; type BlockNumber; } frame_support::decl_storage! { trait Store for Module as TestStorage { // non-getters: pub / $default /// Hello, this is doc! U32: Option; pub PUBU32: Option; U32MYDEF: Option; pub PUBU32MYDEF: Option; // getters: pub / $default // we need at least one type which uses T, otherwise GenesisConfig will complain. GETU32 get(fn u32_getter): T::Origin; pub PUBGETU32 get(fn pub_u32_getter): u32; GETU32WITHCONFIG get(fn u32_getter_with_config) config(): u32; pub PUBGETU32WITHCONFIG get(fn pub_u32_getter_with_config) config(): u32; GETU32MYDEF get(fn u32_getter_mydef): Option; pub PUBGETU32MYDEF get(fn pub_u32_getter_mydef) config(): u32 = 3; GETU32WITHCONFIGMYDEF get(fn u32_getter_with_config_mydef) config(): u32 = 2; pub PUBGETU32WITHCONFIGMYDEF get(fn pub_u32_getter_with_config_mydef) config(): u32 = 1; PUBGETU32WITHCONFIGMYDEFOPT get(fn pub_u32_getter_with_config_mydef_opt) config(): Option; GetU32WithBuilder get(fn u32_with_builder) build(|_| 1): u32; GetOptU32WithBuilderSome get(fn opt_u32_with_builder_some) build(|_| Some(1)): Option; GetOptU32WithBuilderNone get(fn opt_u32_with_builder_none) build(|_| None): Option; // map non-getters: pub / $default MAPU32: map hasher(blake2_128_concat) u32 => Option; pub PUBMAPU32: map hasher(blake2_128_concat) u32 => Option; MAPU32MYDEF: map hasher(blake2_128_concat) u32 => Option; pub PUBMAPU32MYDEF: map hasher(blake2_128_concat) u32 => Option; // map getters: pub / $default GETMAPU32 get(fn map_u32_getter): map hasher(blake2_128_concat) u32 => String; pub PUBGETMAPU32 get(fn pub_map_u32_getter): map hasher(blake2_128_concat) u32 => String; GETMAPU32MYDEF get(fn map_u32_getter_mydef): map hasher(blake2_128_concat) u32 => String = "map".into(); pub PUBGETMAPU32MYDEF get(fn pub_map_u32_getter_mydef): map hasher(blake2_128_concat) u32 => String = "pubmap".into(); COMPLEXTYPE1: ::std::vec::Vec<::Origin>; COMPLEXTYPE2: (Vec)>>, u32); COMPLEXTYPE3: [u32; 25]; } add_extra_genesis { build(|_| {}); } } struct TraitImpl {} impl Trait for TraitImpl { type Origin = u32; type BlockNumber = u32; } const EXPECTED_METADATA: StorageMetadata = StorageMetadata { prefix: DecodeDifferent::Encode("TestStorage"), entries: DecodeDifferent::Encode( &[ StorageEntryMetadata { name: DecodeDifferent::Encode("U32"), modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructU32(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[ " Hello, this is doc!" ]), }, StorageEntryMetadata { name: DecodeDifferent::Encode("PUBU32"), modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructPUBU32(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { name: DecodeDifferent::Encode("U32MYDEF"), modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructU32MYDEF(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { name: DecodeDifferent::Encode("PUBU32MYDEF"), modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructPUBU32MYDEF(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { name: DecodeDifferent::Encode("GETU32"), modifier: StorageEntryModifier::Default, ty: StorageEntryType::Plain(DecodeDifferent::Encode("T::Origin")), default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructGETU32(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { name: DecodeDifferent::Encode("PUBGETU32"), modifier: StorageEntryModifier::Default, ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructPUBGETU32(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { name: DecodeDifferent::Encode("GETU32WITHCONFIG"), modifier: StorageEntryModifier::Default, ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructGETU32WITHCONFIG(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { name: DecodeDifferent::Encode("PUBGETU32WITHCONFIG"), modifier: StorageEntryModifier::Default, ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructPUBGETU32WITHCONFIG(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { name: DecodeDifferent::Encode("GETU32MYDEF"), modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructGETU32MYDEF(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { name: DecodeDifferent::Encode("PUBGETU32MYDEF"), modifier: StorageEntryModifier::Default, ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructPUBGETU32MYDEF(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { name: DecodeDifferent::Encode("GETU32WITHCONFIGMYDEF"), modifier: StorageEntryModifier::Default, ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructGETU32WITHCONFIGMYDEF(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { name: DecodeDifferent::Encode("PUBGETU32WITHCONFIGMYDEF"), modifier: StorageEntryModifier::Default, ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructPUBGETU32WITHCONFIGMYDEF(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { name: DecodeDifferent::Encode("PUBGETU32WITHCONFIGMYDEFOPT"), modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructPUBGETU32WITHCONFIGMYDEFOPT(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { name: DecodeDifferent::Encode("GetU32WithBuilder"), modifier: StorageEntryModifier::Default, ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructGetU32WithBuilder(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { name: DecodeDifferent::Encode("GetOptU32WithBuilderSome"), modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructGetOptU32WithBuilderSome(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { name: DecodeDifferent::Encode("GetOptU32WithBuilderNone"), modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructGetOptU32WithBuilderNone(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { name: DecodeDifferent::Encode("MAPU32"), modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Map { hasher: StorageHasher::Blake2_128Concat, key: DecodeDifferent::Encode("u32"), value: DecodeDifferent::Encode("String"), unused: false, }, default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructMAPU32(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { name: DecodeDifferent::Encode("PUBMAPU32"), modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Map { hasher: StorageHasher::Blake2_128Concat, key: DecodeDifferent::Encode("u32"), value: DecodeDifferent::Encode("String"), unused: false, }, default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructPUBMAPU32(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { name: DecodeDifferent::Encode("MAPU32MYDEF"), modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Map { hasher: StorageHasher::Blake2_128Concat, key: DecodeDifferent::Encode("u32"), value: DecodeDifferent::Encode("String"), unused: false, }, default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructMAPU32MYDEF(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { name: DecodeDifferent::Encode("PUBMAPU32MYDEF"), modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Map { hasher: StorageHasher::Blake2_128Concat, key: DecodeDifferent::Encode("u32"), value: DecodeDifferent::Encode("String"), unused: false, }, default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructPUBMAPU32MYDEF(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { name: DecodeDifferent::Encode("GETMAPU32"), modifier: StorageEntryModifier::Default, ty: StorageEntryType::Map { hasher: StorageHasher::Blake2_128Concat, key: DecodeDifferent::Encode("u32"), value: DecodeDifferent::Encode("String"), unused: false, }, default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructGETMAPU32(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { name: DecodeDifferent::Encode("PUBGETMAPU32"), modifier: StorageEntryModifier::Default, ty: StorageEntryType::Map { hasher: StorageHasher::Blake2_128Concat, key: DecodeDifferent::Encode("u32"), value: DecodeDifferent::Encode("String"), unused: false, }, default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructPUBGETMAPU32(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { name: DecodeDifferent::Encode("GETMAPU32MYDEF"), modifier: StorageEntryModifier::Default, ty: StorageEntryType::Map { hasher: StorageHasher::Blake2_128Concat, key: DecodeDifferent::Encode("u32"), value: DecodeDifferent::Encode("String"), unused: false, }, default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructGETMAPU32MYDEF(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { name: DecodeDifferent::Encode("PUBGETMAPU32MYDEF"), modifier: StorageEntryModifier::Default, ty: StorageEntryType::Map { hasher: StorageHasher::Blake2_128Concat, key: DecodeDifferent::Encode("u32"), value: DecodeDifferent::Encode("String"), unused: false, }, default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructPUBGETMAPU32MYDEF(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { name: DecodeDifferent::Encode("COMPLEXTYPE1"), modifier: StorageEntryModifier::Default, ty: StorageEntryType::Plain(DecodeDifferent::Encode("::std::vec::Vec<::Origin>")), default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructCOMPLEXTYPE1(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { name: DecodeDifferent::Encode("COMPLEXTYPE2"), modifier: StorageEntryModifier::Default, ty: StorageEntryType::Plain(DecodeDifferent::Encode("(Vec)>>, u32)")), default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructCOMPLEXTYPE2(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, StorageEntryMetadata { name: DecodeDifferent::Encode("COMPLEXTYPE3"), modifier: StorageEntryModifier::Default, ty: StorageEntryType::Plain(DecodeDifferent::Encode("[u32; 25]")), default: DecodeDifferent::Encode( DefaultByteGetter(&__GetByteStructCOMPLEXTYPE3(PhantomData::)) ), documentation: DecodeDifferent::Encode(&[]), }, ] ), }; #[test] fn store_metadata() { let metadata = Module::::storage_metadata(); pretty_assertions::assert_eq!(EXPECTED_METADATA, metadata); } #[test] fn check_genesis_config() { let config = GenesisConfig::default(); assert_eq!(config.u32_getter_with_config, 0u32); assert_eq!(config.pub_u32_getter_with_config, 0u32); assert_eq!(config.pub_u32_getter_mydef, 3u32); assert_eq!(config.u32_getter_with_config_mydef, 2u32); assert_eq!(config.pub_u32_getter_with_config_mydef, 1u32); assert_eq!(config.pub_u32_getter_with_config_mydef_opt, 0u32); } #[test] fn check_builder_config() { let config = GenesisConfig::default(); let storage = config.build_storage().unwrap(); TestExternalities::from(storage).execute_with(|| { assert_eq!(Module::::u32_with_builder(), 1); assert_eq!(Module::::opt_u32_with_builder_some(), Some(1)); assert_eq!(Module::::opt_u32_with_builder_none(), None); }) } } #[cfg(test)] #[allow(dead_code)] mod test2 { pub trait Trait { type Origin; type BlockNumber; } frame_support::decl_module! { pub struct Module for enum Call where origin: T::Origin {} } type PairOf = (T, T); frame_support::decl_storage! { trait Store for Module as TestStorage { SingleDef : u32; PairDef : PairOf; Single : Option; Pair : (u32, u32); } add_extra_genesis { config(_marker) : ::std::marker::PhantomData; config(extra_field) : u32 = 32; build(|_| {}); } } struct TraitImpl {} impl Trait for TraitImpl { type Origin = u32; type BlockNumber = u32; } } #[cfg(test)] #[allow(dead_code)] mod test3 { pub trait Trait { type Origin; type BlockNumber; } frame_support::decl_module! { pub struct Module for enum Call where origin: T::Origin {} } frame_support::decl_storage! { trait Store for Module as Test { Foo get(fn foo) config(initial_foo): u32; } } type PairOf = (T, T); struct TraitImpl {} impl Trait for TraitImpl { type Origin = u32; type BlockNumber = u32; } } #[cfg(test)] #[allow(dead_code)] mod test_append_and_len { use sp_io::TestExternalities; use codec::{Encode, Decode}; pub trait Trait { type Origin; type BlockNumber; } frame_support::decl_module! { pub struct Module for enum Call where origin: T::Origin {} } #[derive(PartialEq, Eq, Clone, Encode, Decode)] struct NoDef(u32); frame_support::decl_storage! { trait Store for Module as Test { NoDefault: Option; JustVec: Vec; JustVecWithDefault: Vec = vec![6, 9]; OptionVec: Option>; MapVec: map hasher(blake2_128_concat) u32 => Vec; MapVecWithDefault: map hasher(blake2_128_concat) u32 => Vec = vec![6, 9]; OptionMapVec: map hasher(blake2_128_concat) u32 => Option>; DoubleMapVec: double_map hasher(blake2_128_concat) u32, hasher(blake2_128_concat) u32 => Vec; DoubleMapVecWithDefault: double_map hasher(blake2_128_concat) u32, hasher(blake2_128_concat) u32 => Vec = vec![6, 9]; OptionDoubleMapVec: double_map hasher(blake2_128_concat) u32, hasher(blake2_128_concat) u32 => Option>; } } struct Test {} impl Trait for Test { type Origin = u32; type BlockNumber = u32; } #[test] fn default_for_option() { TestExternalities::default().execute_with(|| { assert_eq!(OptionVec::get(), None); assert_eq!(JustVec::get(), vec![]); }); } #[test] fn append_works() { TestExternalities::default().execute_with(|| { let _ = MapVec::append(1, [1, 2, 3].iter()); let _ = MapVec::append(1, [4, 5].iter()); assert_eq!(MapVec::get(1), vec![1, 2, 3, 4, 5]); let _ = JustVec::append([1, 2, 3].iter()); let _ = JustVec::append([4, 5].iter()); assert_eq!(JustVec::get(), vec![1, 2, 3, 4, 5]); }); } #[test] fn append_works_for_default() { TestExternalities::default().execute_with(|| { assert_eq!(JustVecWithDefault::get(), vec![6, 9]); let _ = JustVecWithDefault::append([1].iter()); assert_eq!(JustVecWithDefault::get(), vec![6, 9, 1]); assert_eq!(MapVecWithDefault::get(0), vec![6, 9]); let _ = MapVecWithDefault::append(0, [1].iter()); assert_eq!(MapVecWithDefault::get(0), vec![6, 9, 1]); assert_eq!(OptionVec::get(), None); let _ = OptionVec::append([1].iter()); assert_eq!(OptionVec::get(), Some(vec![1])); }); } #[test] fn append_or_put_works() { TestExternalities::default().execute_with(|| { let _ = MapVec::append_or_insert(1, &[1, 2, 3][..]); let _ = MapVec::append_or_insert(1, &[4, 5][..]); assert_eq!(MapVec::get(1), vec![1, 2, 3, 4, 5]); let _ = JustVec::append_or_put(&[1, 2, 3][..]); let _ = JustVec::append_or_put(&[4, 5][..]); assert_eq!(JustVec::get(), vec![1, 2, 3, 4, 5]); let _ = OptionVec::append_or_put(&[1, 2, 3][..]); let _ = OptionVec::append_or_put(&[4, 5][..]); assert_eq!(OptionVec::get(), Some(vec![1, 2, 3, 4, 5])); }); } #[test] fn len_works() { TestExternalities::default().execute_with(|| { JustVec::put(&vec![1, 2, 3, 4]); OptionVec::put(&vec![1, 2, 3, 4, 5]); MapVec::insert(1, &vec![1, 2, 3, 4, 5, 6]); DoubleMapVec::insert(0, 1, &vec![1, 2]); assert_eq!(JustVec::decode_len().unwrap(), 4); assert_eq!(OptionVec::decode_len().unwrap(), 5); assert_eq!(MapVec::decode_len(1).unwrap(), 6); assert_eq!(DoubleMapVec::decode_len(0, 1).unwrap(), 2); }); } #[test] fn len_works_for_default() { TestExternalities::default().execute_with(|| { // vec assert_eq!(JustVec::get(), vec![]); assert_eq!(JustVec::decode_len(), Ok(0)); assert_eq!(JustVecWithDefault::get(), vec![6, 9]); assert_eq!(JustVecWithDefault::decode_len(), Ok(2)); assert_eq!(OptionVec::get(), None); assert_eq!(OptionVec::decode_len(), Ok(0)); // map assert_eq!(MapVec::get(0), vec![]); assert_eq!(MapVec::decode_len(0), Ok(0)); assert_eq!(MapVecWithDefault::get(0), vec![6, 9]); assert_eq!(MapVecWithDefault::decode_len(0), Ok(2)); assert_eq!(OptionMapVec::get(0), None); assert_eq!(OptionMapVec::decode_len(0), Ok(0)); // Double map assert_eq!(DoubleMapVec::get(0, 0), vec![]); assert_eq!(DoubleMapVec::decode_len(0, 1), Ok(0)); assert_eq!(DoubleMapVecWithDefault::get(0, 0), vec![6, 9]); assert_eq!(DoubleMapVecWithDefault::decode_len(0, 1), Ok(2)); assert_eq!(OptionDoubleMapVec::get(0, 0), None); assert_eq!(OptionDoubleMapVec::decode_len(0, 1), Ok(0)); }); } }