// This file is part of Substrate. // Copyright (C) 2017-2020 Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. use crate::*; use mock::{*, Origin}; use sp_core::H256; use sp_runtime::DispatchError; use frame_support::weights::WithPostDispatchInfo; #[test] fn origin_works() { let o = Origin::from(RawOrigin::::Signed(1u64)); let x: Result, Origin> = o.into(); assert_eq!(x.unwrap(), RawOrigin::::Signed(1u64)); } #[test] fn stored_map_works() { new_test_ext().execute_with(|| { System::insert(&0, 42); assert!(System::allow_death(&0)); System::inc_ref(&0); assert!(!System::allow_death(&0)); System::insert(&0, 69); assert!(!System::allow_death(&0)); System::dec_ref(&0); assert!(System::allow_death(&0)); assert!(KILLED.with(|r| r.borrow().is_empty())); System::kill_account(&0); assert_eq!(KILLED.with(|r| r.borrow().clone()), vec![0u64]); }); } #[test] fn deposit_event_should_work() { new_test_ext().execute_with(|| { System::initialize( &1, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default(), InitKind::Full, ); System::note_finished_extrinsics(); System::deposit_event(SysEvent::CodeUpdated); System::finalize(); assert_eq!( System::events(), vec![ EventRecord { phase: Phase::Finalization, event: SysEvent::CodeUpdated, topics: vec![], } ] ); System::initialize( &2, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default(), InitKind::Full, ); System::deposit_event(SysEvent::NewAccount(32)); System::note_finished_initialize(); System::deposit_event(SysEvent::KilledAccount(42)); System::note_applied_extrinsic(&Ok(().into()), Default::default()); System::note_applied_extrinsic( &Err(DispatchError::BadOrigin.into()), Default::default() ); System::note_finished_extrinsics(); System::deposit_event(SysEvent::NewAccount(3)); System::finalize(); assert_eq!( System::events(), vec![ EventRecord { phase: Phase::Initialization, event: SysEvent::NewAccount(32), topics: vec![], }, EventRecord { phase: Phase::ApplyExtrinsic(0), event: SysEvent::KilledAccount(42), topics: vec![] }, EventRecord { phase: Phase::ApplyExtrinsic(0), event: SysEvent::ExtrinsicSuccess(Default::default()), topics: vec![] }, EventRecord { phase: Phase::ApplyExtrinsic(1), event: SysEvent::ExtrinsicFailed( DispatchError::BadOrigin.into(), Default::default() ), topics: vec![] }, EventRecord { phase: Phase::Finalization, event: SysEvent::NewAccount(3), topics: vec![] }, ] ); }); } #[test] fn deposit_event_uses_actual_weight() { new_test_ext().execute_with(|| { System::initialize( &1, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default(), InitKind::Full, ); System::note_finished_initialize(); let pre_info = DispatchInfo { weight: 1000, .. Default::default() }; System::note_applied_extrinsic( &Ok(Some(300).into()), pre_info, ); System::note_applied_extrinsic( &Ok(Some(1000).into()), pre_info, ); System::note_applied_extrinsic( // values over the pre info should be capped at pre dispatch value &Ok(Some(1200).into()), pre_info, ); System::note_applied_extrinsic( &Err(DispatchError::BadOrigin.with_weight(999)), pre_info, ); assert_eq!( System::events(), vec![ EventRecord { phase: Phase::ApplyExtrinsic(0), event: SysEvent::ExtrinsicSuccess( DispatchInfo { weight: 300, .. Default::default() }, ), topics: vec![] }, EventRecord { phase: Phase::ApplyExtrinsic(1), event: SysEvent::ExtrinsicSuccess( DispatchInfo { weight: 1000, .. Default::default() }, ), topics: vec![] }, EventRecord { phase: Phase::ApplyExtrinsic(2), event: SysEvent::ExtrinsicSuccess( DispatchInfo { weight: 1000, .. Default::default() }, ), topics: vec![] }, EventRecord { phase: Phase::ApplyExtrinsic(3), event: SysEvent::ExtrinsicFailed( DispatchError::BadOrigin.into(), DispatchInfo { weight: 999, .. Default::default() }, ), topics: vec![] }, ] ); }); } #[test] fn deposit_event_topics() { new_test_ext().execute_with(|| { const BLOCK_NUMBER: u64 = 1; System::initialize( &BLOCK_NUMBER, &[0u8; 32].into(), &[0u8; 32].into(), &Default::default(), InitKind::Full, ); System::note_finished_extrinsics(); let topics = vec![ H256::repeat_byte(1), H256::repeat_byte(2), H256::repeat_byte(3), ]; // We deposit a few events with different sets of topics. System::deposit_event_indexed(&topics[0..3], SysEvent::NewAccount(1)); System::deposit_event_indexed(&topics[0..1], SysEvent::NewAccount(2)); System::deposit_event_indexed(&topics[1..2], SysEvent::NewAccount(3)); System::finalize(); // Check that topics are reflected in the event record. assert_eq!( System::events(), vec![ EventRecord { phase: Phase::Finalization, event: SysEvent::NewAccount(1), topics: topics[0..3].to_vec(), }, EventRecord { phase: Phase::Finalization, event: SysEvent::NewAccount(2), topics: topics[0..1].to_vec(), }, EventRecord { phase: Phase::Finalization, event: SysEvent::NewAccount(3), topics: topics[1..2].to_vec(), } ] ); // Check that the topic-events mapping reflects the deposited topics. // Note that these are indexes of the events. assert_eq!( System::event_topics(&topics[0]), vec![(BLOCK_NUMBER, 0), (BLOCK_NUMBER, 1)], ); assert_eq!( System::event_topics(&topics[1]), vec![(BLOCK_NUMBER, 0), (BLOCK_NUMBER, 2)], ); assert_eq!( System::event_topics(&topics[2]), vec![(BLOCK_NUMBER, 0)], ); }); } #[test] fn prunes_block_hash_mappings() { new_test_ext().execute_with(|| { // simulate import of 15 blocks for n in 1..=15 { System::initialize( &n, &[n as u8 - 1; 32].into(), &[0u8; 32].into(), &Default::default(), InitKind::Full, ); System::finalize(); } // first 5 block hashes are pruned for n in 0..5 { assert_eq!( System::block_hash(n), H256::zero(), ); } // the remaining 10 are kept for n in 5..15 { assert_eq!( System::block_hash(n), [n as u8; 32].into(), ); } }) } #[test] fn set_code_checks_works() { struct CallInWasm(Vec); impl sp_core::traits::CallInWasm for CallInWasm { fn call_in_wasm( &self, _: &[u8], _: Option>, _: &str, _: &[u8], _: &mut dyn sp_externalities::Externalities, _: sp_core::traits::MissingHostFunctions, ) -> Result, String> { Ok(self.0.clone()) } } let test_data = vec![ ("test", 1, 2, Err(Error::::SpecVersionNeedsToIncrease)), ("test", 1, 1, Err(Error::::SpecVersionNeedsToIncrease)), ("test2", 1, 1, Err(Error::::InvalidSpecName)), ("test", 2, 1, Ok(())), ("test", 0, 1, Err(Error::::SpecVersionNeedsToIncrease)), ("test", 1, 0, Err(Error::::SpecVersionNeedsToIncrease)), ]; for (spec_name, spec_version, impl_version, expected) in test_data.into_iter() { let version = RuntimeVersion { spec_name: spec_name.into(), spec_version, impl_version, ..Default::default() }; let call_in_wasm = CallInWasm(version.encode()); let mut ext = new_test_ext(); ext.register_extension(sp_core::traits::CallInWasmExt::new(call_in_wasm)); ext.execute_with(|| { let res = System::set_code( RawOrigin::Root.into(), vec![1, 2, 3, 4], ); assert_eq!(expected.map_err(DispatchError::from), res); }); } } #[test] fn set_code_with_real_wasm_blob() { let executor = substrate_test_runtime_client::new_native_executor(); let mut ext = new_test_ext(); ext.register_extension(sp_core::traits::CallInWasmExt::new(executor)); ext.execute_with(|| { System::set_block_number(1); System::set_code( RawOrigin::Root.into(), substrate_test_runtime_client::runtime::wasm_binary_unwrap().to_vec(), ).unwrap(); assert_eq!( System::events(), vec![EventRecord { phase: Phase::Initialization, event: SysEvent::CodeUpdated, topics: vec![], }], ); }); } #[test] fn runtime_upgraded_with_set_storage() { let executor = substrate_test_runtime_client::new_native_executor(); let mut ext = new_test_ext(); ext.register_extension(sp_core::traits::CallInWasmExt::new(executor)); ext.execute_with(|| { System::set_storage( RawOrigin::Root.into(), vec![( well_known_keys::CODE.to_vec(), substrate_test_runtime_client::runtime::wasm_binary_unwrap().to_vec() )], ).unwrap(); }); } #[test] fn events_not_emitted_during_genesis() { new_test_ext().execute_with(|| { // Block Number is zero at genesis assert!(System::block_number().is_zero()); System::on_created_account(Default::default()); assert!(System::events().is_empty()); // Events will be emitted starting on block 1 System::set_block_number(1); System::on_created_account(Default::default()); assert!(System::events().len() == 1); }); } #[test] fn ensure_one_of_works() { fn ensure_root_or_signed(o: RawOrigin) -> Result, Origin> { EnsureOneOf::, EnsureSigned>::try_origin(o.into()) } assert_eq!(ensure_root_or_signed(RawOrigin::Root).unwrap(), Either::Left(())); assert_eq!(ensure_root_or_signed(RawOrigin::Signed(0)).unwrap(), Either::Right(0)); assert!(ensure_root_or_signed(RawOrigin::None).is_err()) }