referrerpolicy=no-referrer-when-downgrade

polkadot_test_client/
lib.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Polkadot.
3
4// Polkadot is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Polkadot is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
16
17//! A Polkadot test client.
18//!
19//! This test client is using the Polkadot test runtime.
20
21mod block_builder;
22
23use polkadot_primitives::Block;
24use sp_runtime::BuildStorage;
25use std::sync::Arc;
26
27pub use block_builder::*;
28pub use polkadot_test_runtime as runtime;
29pub use polkadot_test_service::{
30	construct_extrinsic, construct_transfer_extrinsic, Client, FullBackend,
31};
32pub use substrate_test_client::*;
33
34/// Test client executor.
35pub type Executor = client::LocalCallExecutor<
36	Block,
37	FullBackend,
38	WasmExecutor<(sp_io::SubstrateHostFunctions, frame_benchmarking::benchmarking::HostFunctions)>,
39>;
40
41/// Test client builder for Polkadot.
42pub type TestClientBuilder =
43	substrate_test_client::TestClientBuilder<Block, Executor, FullBackend, GenesisParameters>;
44
45/// `LongestChain` type for the test runtime/client.
46pub type LongestChain = sc_consensus::LongestChain<FullBackend, Block>;
47
48/// Parameters of test-client builder with test-runtime.
49#[derive(Default)]
50pub struct GenesisParameters;
51
52impl substrate_test_client::GenesisInit for GenesisParameters {
53	fn genesis_storage(&self) -> Storage {
54		polkadot_test_service::chain_spec::polkadot_local_testnet_config()
55			.build_storage()
56			.expect("Builds test runtime genesis storage")
57	}
58}
59
60/// A `test-runtime` extensions to `TestClientBuilder`.
61pub trait TestClientBuilderExt: Sized {
62	/// Build the test client.
63	fn build(self) -> Client {
64		self.build_with_longest_chain().0
65	}
66
67	/// Build the test client and longest chain selector.
68	fn build_with_longest_chain(self) -> (Client, LongestChain);
69}
70
71impl TestClientBuilderExt for TestClientBuilder {
72	fn build_with_longest_chain(self) -> (Client, LongestChain) {
73		let executor = WasmExecutor::builder().build();
74		let executor = client::LocalCallExecutor::new(
75			self.backend().clone(),
76			executor.clone(),
77			Default::default(),
78			ExecutionExtensions::new(Default::default(), Arc::new(executor)),
79		)
80		.unwrap();
81
82		self.build_with_executor(executor)
83	}
84}
85
86/// A `TestClientBuilder` with default backend and executor.
87pub trait DefaultTestClientBuilderExt: Sized {
88	/// Create new `TestClientBuilder`
89	fn new() -> Self;
90}
91
92impl DefaultTestClientBuilderExt for TestClientBuilder {
93	fn new() -> Self {
94		Self::with_default_backend()
95	}
96}
97
98#[cfg(test)]
99mod tests {
100	use super::*;
101	use sp_consensus::BlockOrigin;
102
103	#[test]
104	fn ensure_test_client_can_build_and_import_block() {
105		let client = TestClientBuilder::new().build();
106
107		let block_builder = client.init_polkadot_block_builder();
108		let block = block_builder.build().expect("Finalizes the block").block;
109
110		futures::executor::block_on(client.import(BlockOrigin::Own, block))
111			.expect("Imports the block");
112	}
113
114	#[test]
115	fn ensure_test_client_can_push_extrinsic() {
116		let client = TestClientBuilder::new().build();
117
118		let transfer = construct_transfer_extrinsic(
119			&client,
120			sp_keyring::Sr25519Keyring::Alice,
121			sp_keyring::Sr25519Keyring::Bob,
122			1000,
123		);
124		let mut block_builder = client.init_polkadot_block_builder();
125		block_builder.push_polkadot_extrinsic(transfer).expect("Pushes extrinsic");
126
127		let block = block_builder.build().expect("Finalizes the block").block;
128
129		futures::executor::block_on(client.import(BlockOrigin::Own, block))
130			.expect("Imports the block");
131	}
132}