Implements mocking of runtime apis (#5448)

* Implements mocking of runtime apis

This pr adds support for easily mock runtime api implementations for
tests by using the `mock_impl_runtime_apis!` macro. The syntax is
similar to `impl_runtime_apis!`. The mocked implementation automatically
implements `ApiExt`, `ApiErrorExt` and `Core` as these are required by
the runtime api traits, but not required in tests or only a subset of them.

* Fix warnings

* Update primitives/api/proc-macro/src/utils.rs

Co-Authored-By: Nikolay Volf <nikvolf@gmail.com>

* Review feedback

Co-authored-by: Nikolay Volf <nikvolf@gmail.com>
This commit is contained in:
Bastian Köcher
2020-03-31 13:46:07 +02:00
committed by GitHub
parent b4d83a4b54
commit 954dca689d
19 changed files with 899 additions and 258 deletions
@@ -21,8 +21,8 @@ use futures::executor::block_on;
use futures::future::poll_fn;
use libp2p::{kad, PeerId};
use sp_api::{ApiExt, ApiErrorExt, Core, RuntimeVersion, StorageProof, ProvideRuntimeApi, ApiRef};
use sp_core::{testing::KeyStore, ExecutionContext, NativeOrEncoded};
use sp_api::{ProvideRuntimeApi, ApiRef};
use sp_core::testing::KeyStore;
use sp_runtime::traits::{Zero, Block as BlockT, NumberFor};
use substrate_test_runtime_client::runtime::Block;
@@ -99,8 +99,7 @@ impl ProvideRuntimeApi<Block> for TestApi {
fn runtime_api<'a>(&'a self) -> ApiRef<'a, Self::Api> {
RuntimeApi {
authorities: self.authorities.clone(),
}
.into()
}.into()
}
}
@@ -149,90 +148,13 @@ struct RuntimeApi {
authorities: Vec<AuthorityId>,
}
impl Core<Block> for RuntimeApi {
fn Core_version_runtime_api_impl(
&self,
_: &BlockId<Block>,
_: ExecutionContext,
_: Option<()>,
_: Vec<u8>,
) -> std::result::Result<NativeOrEncoded<RuntimeVersion>, sp_blockchain::Error> {
unimplemented!("Not required for testing!")
}
sp_api::mock_impl_runtime_apis! {
impl AuthorityDiscoveryApi<Block> for RuntimeApi {
type Error = sp_blockchain::Error;
fn Core_execute_block_runtime_api_impl(
&self,
_: &BlockId<Block>,
_: ExecutionContext,
_: Option<Block>,
_: Vec<u8>,
) -> std::result::Result<NativeOrEncoded<()>, sp_blockchain::Error> {
unimplemented!("Not required for testing!")
}
fn Core_initialize_block_runtime_api_impl(
&self,
_: &BlockId<Block>,
_: ExecutionContext,
_: Option<&<Block as BlockT>::Header>,
_: Vec<u8>,
) -> std::result::Result<NativeOrEncoded<()>, sp_blockchain::Error> {
unimplemented!("Not required for testing!")
}
}
impl ApiErrorExt for RuntimeApi {
type Error = sp_blockchain::Error;
}
impl ApiExt<Block> for RuntimeApi {
type StateBackend = <
substrate_test_runtime_client::Backend as sc_client_api::backend::Backend<Block>
>::State;
fn map_api_result<F: FnOnce(&Self) -> std::result::Result<R, E>, R, E>(
&self,
_: F
) -> std::result::Result<R, E> {
unimplemented!("Not required for testing!")
}
fn runtime_version_at(
&self,
_: &BlockId<Block>,
) -> std::result::Result<RuntimeVersion, Self::Error> {
unimplemented!("Not required for testing!")
}
fn record_proof(&mut self) {
unimplemented!("Not required for testing!")
}
fn extract_proof(&mut self) -> Option<StorageProof> {
unimplemented!("Not required for testing!")
}
fn into_storage_changes(
&self,
_: &Self::StateBackend,
_: Option<&sp_api::ChangesTrieState<sp_api::HashFor<Block>, sp_api::NumberFor<Block>>>,
_: <Block as sp_api::BlockT>::Hash,
) -> std::result::Result<sp_api::StorageChanges<Self::StateBackend, Block>, String>
where Self: Sized
{
unimplemented!("Not required for testing!")
}
}
impl AuthorityDiscoveryApi<Block> for RuntimeApi {
fn AuthorityDiscoveryApi_authorities_runtime_api_impl(
&self,
_: &BlockId<Block>,
_: ExecutionContext,
_: Option<()>,
_: Vec<u8>,
) -> std::result::Result<NativeOrEncoded<Vec<AuthorityId>>, sp_blockchain::Error> {
return Ok(NativeOrEncoded::Native(self.authorities.clone()));
fn authorities(&self) -> Vec<AuthorityId> {
self.authorities.clone()
}
}
}