From fcea97281661f0a0a4c28e46edbfb1238043471e Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Tue, 14 Jul 2020 13:25:48 +0200 Subject: [PATCH] test-utils: test executor, backend and function to create test client (#73) * test-utils: basic executor and backend definitions * test-utils: implement function to create a new test client * Fix indentation --- Cargo.lock | 44 ++++++++++- Cargo.toml | 1 + template/test-utils/client/Cargo.toml | 18 +++++ template/test-utils/client/src/lib.rs | 110 ++++++++++++++++++++++++++ 4 files changed, 171 insertions(+), 2 deletions(-) create mode 100644 template/test-utils/client/Cargo.toml create mode 100644 template/test-utils/client/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 1871363c2ef19..931a3aa64b798 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1341,6 +1341,21 @@ dependencies = [ "substrate-wasm-builder-runner", ] +[[package]] +name = "frontier-template-test-client" +version = "0.1.0" +dependencies = [ + "frontier-template-runtime", + "parity-scale-codec", + "sc-client-api", + "sc-consensus", + "sc-executor", + "sc-light", + "sp-api", + "sp-runtime", + "substrate-test-client", +] + [[package]] name = "fs-swap" version = "0.2.4" @@ -5133,9 +5148,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.53" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "993948e75b189211a9b31a7528f950c6adc21f9720b6438ff80a7fa2f864cea2" +checksum = "3433e879a558dde8b5e8feb2a04899cf34fdde1fafb894687e52105fc1162ac3" dependencies = [ "itoa", "ryu", @@ -5980,6 +5995,31 @@ dependencies = [ "tokio 0.2.21", ] +[[package]] +name = "substrate-test-client" +version = "2.0.0-rc4" +dependencies = [ + "futures 0.1.29", + "futures 0.3.5", + "hash-db", + "hex", + "parity-scale-codec", + "sc-client-api", + "sc-client-db", + "sc-consensus", + "sc-executor", + "sc-light", + "sc-service", + "serde", + "serde_json", + "sp-blockchain", + "sp-consensus", + "sp-core", + "sp-keyring", + "sp-runtime", + "sp-state-machine", +] + [[package]] name = "substrate-wasm-builder-runner" version = "1.0.6" diff --git a/Cargo.toml b/Cargo.toml index 7d921631bbe8c..8964a7c89e155 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ members = [ "rpc/primitives", "template/node", "template/runtime", + "template/test-utils/client", ] exclude = ["vendor"] diff --git a/template/test-utils/client/Cargo.toml b/template/test-utils/client/Cargo.toml new file mode 100644 index 0000000000000..9f9c7c9cdce79 --- /dev/null +++ b/template/test-utils/client/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "frontier-template-test-client" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +description = "Ethereum RPC (web3) compatibility layer for Substrate." +license = "GPL-3.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "1.3.1" } +sp-runtime = { path = "../../../vendor/substrate/primitives/runtime" } +sp-api = { path = "../../../vendor/substrate/primitives/api" } +sc-executor = { path = "../../../vendor/substrate/client/executor" } +sc-light = { path = "../../../vendor/substrate/client/light" } +sc-consensus = { path = "../../../vendor/substrate/client/consensus/common" } +sc-client-api = { path = "../../../vendor/substrate/client/api" } +substrate-test-client = { path = "../../../vendor/substrate/test-utils/client" } +frontier-template-runtime = { path = "../../runtime" } \ No newline at end of file diff --git a/template/test-utils/client/src/lib.rs b/template/test-utils/client/src/lib.rs new file mode 100644 index 0000000000000..6e863feeac4a8 --- /dev/null +++ b/template/test-utils/client/src/lib.rs @@ -0,0 +1,110 @@ +use std::sync::Arc; + +pub use substrate_test_client::*; +pub use frontier_template_runtime as runtime; +use sp_runtime::traits::HashFor; + +sc_executor::native_executor_instance! { + pub LocalExecutor, + runtime::api::dispatch, + runtime::native_version, +} + +pub type Backend = substrate_test_client::Backend; + +pub type Executor = client::LocalCallExecutor< + Backend, + NativeExecutor, +>; + +pub type LightBackend = substrate_test_client::LightBackend; + +pub type LightExecutor = sc_light::GenesisCallExecutor< + LightBackend, + client::LocalCallExecutor< + sc_light::Backend< + sc_client_db::light::LightStorage, + HashFor + >, + NativeExecutor + > +>; + +/// Parameters of test-client builder with test-runtime. +#[derive(Default)] +pub struct GenesisParameters; + +impl substrate_test_client::GenesisInit for GenesisParameters { + fn genesis_storage(&self) -> Storage { + Storage::default() + } +} + +/// A `TestClient` with `test-runtime` builder. +pub type TestClientBuilder = substrate_test_client::TestClientBuilder< + runtime::opaque::Block, + E, + B, + GenesisParameters, +>; + +/// Test client type with `LocalExecutor` and generic Backend. +pub type Client = client::Client< + B, + client::LocalCallExecutor>, + runtime::opaque::Block, + runtime::RuntimeApi, +>; + +/// A test client with default backend. +pub type TestClient = Client; + +/// A `TestClientBuilder` with default backend and executor. +pub trait DefaultTestClientBuilderExt: Sized { + /// Create new `TestClientBuilder` + fn new() -> Self; +} + +impl DefaultTestClientBuilderExt for TestClientBuilder { + fn new() -> Self { + Self::with_default_backend() + } +} + +/// A `test-runtime` extensions to `TestClientBuilder`. +pub trait TestClientBuilderExt: Sized { + /// Build the test client. + fn build(self) -> Client { + self.build_with_longest_chain().0 + } + + /// Build the test client and longest chain selector. + fn build_with_longest_chain(self) -> (Client, sc_consensus::LongestChain); + + /// Build the test client and the backend. + fn build_with_backend(self) -> (Client, Arc); +} + +impl TestClientBuilderExt for TestClientBuilder< + client::LocalCallExecutor>, + B +> where + B: sc_client_api::backend::Backend + 'static, + // Rust bug: https://github.com/rust-lang/rust/issues/24159 + >::State: + sp_api::StateBackend>, +{ + fn build_with_longest_chain(self) -> (Client, sc_consensus::LongestChain) { + self.build_with_native_executor(None) + } + + fn build_with_backend(self) -> (Client, Arc) { + let backend = self.backend(); + (self.build_with_native_executor(None).0, backend) + } +} + +/// Creates new client instance used for tests. +pub fn new() -> Client { + TestClientBuilder::new().build() +}