// This file is part of Substrate. // Copyright (C) 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. //! Tests for `pallet-example-tasks`. #![cfg(test)] use crate::{mock::*, Numbers}; #[cfg(feature = "experimental")] use codec::Decode; use frame_support::traits::Task; #[cfg(feature = "experimental")] use sp_core::offchain::{testing, OffchainWorkerExt, TransactionPoolExt}; use sp_runtime::BuildStorage; #[cfg(feature = "experimental")] use frame_support::{assert_noop, assert_ok}; // This function basically just builds a genesis storage key/value store according to // our desired mockup. pub fn new_test_ext() -> sp_io::TestExternalities { let t = RuntimeGenesisConfig { // We use default for brevity, but you can configure as desired if needed. system: Default::default(), } .build_storage() .unwrap(); t.into() } #[test] fn task_enumerate_works() { new_test_ext().execute_with(|| { Numbers::::insert(0, 1); assert_eq!(crate::pallet::Task::::iter().collect::>().len(), 1); }); } #[test] fn runtime_task_enumerate_works_via_frame_system_config() { new_test_ext().execute_with(|| { Numbers::::insert(0, 1); Numbers::::insert(1, 4); assert_eq!( ::RuntimeTask::iter().collect::>().len(), 2 ); }); } #[test] fn runtime_task_enumerate_works_via_pallet_config() { new_test_ext().execute_with(|| { Numbers::::insert(1, 4); assert_eq!( ::RuntimeTask::iter() .collect::>() .len(), 1 ); }); } #[test] fn task_index_works_at_pallet_level() { new_test_ext().execute_with(|| { assert_eq!(crate::pallet::Task::::AddNumberIntoTotal { i: 2u32 }.task_index(), 0); }); } #[test] fn task_index_works_at_runtime_level() { new_test_ext().execute_with(|| { assert_eq!( ::RuntimeTask::TasksExample(crate::pallet::Task::< Runtime, >::AddNumberIntoTotal { i: 1u32 }) .task_index(), 0 ); }); } #[cfg(feature = "experimental")] #[test] fn task_execution_works() { new_test_ext().execute_with(|| { System::set_block_number(1); Numbers::::insert(0, 1); Numbers::::insert(1, 4); let task = ::RuntimeTask::TasksExample(crate::pallet::Task::< Runtime, >::AddNumberIntoTotal { i: 1u32, }); assert_ok!(System::do_task(RuntimeOrigin::signed(1), task.clone(),)); assert_eq!(Numbers::::get(0), Some(1)); assert_eq!(Numbers::::get(1), None); assert_eq!(crate::Total::::get(), (1, 4)); System::assert_last_event(frame_system::Event::::TaskCompleted { task }.into()); }); } #[cfg(feature = "experimental")] #[test] fn task_execution_fails_for_invalid_task() { new_test_ext().execute_with(|| { Numbers::::insert(1, 4); assert_noop!( System::do_task( RuntimeOrigin::signed(1), ::RuntimeTask::TasksExample( crate::pallet::Task::::AddNumberIntoTotal { i: 0u32 } ), ), frame_system::Error::::InvalidTask ); }); } #[cfg(feature = "experimental")] #[test] fn task_with_offchain_worker() { let (offchain, _offchain_state) = testing::TestOffchainExt::new(); let (pool, pool_state) = testing::TestTransactionPoolExt::new(); let mut t = sp_io::TestExternalities::default(); t.register_extension(OffchainWorkerExt::new(offchain)); t.register_extension(TransactionPoolExt::new(pool)); t.execute_with(|| { advance_to(1); assert!(pool_state.read().transactions.is_empty()); Numbers::::insert(0, 10); assert_eq!(crate::Total::::get(), (0, 0)); advance_to(2); let tx = pool_state.write().transactions.pop().unwrap(); assert!(pool_state.read().transactions.is_empty()); let tx = Extrinsic::decode(&mut &*tx).unwrap(); assert_eq!(tx.signature, None); }); }