Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit ea5ea42

Browse files
bkchrNikVolf
andauthored
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>
1 parent a691281 commit ea5ea42

19 files changed

+899
-258
lines changed

client/authority-discovery/src/tests.rs

+9-87
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ use futures::executor::block_on;
2121
use futures::future::poll_fn;
2222
use libp2p::{kad, PeerId};
2323

24-
use sp_api::{ApiExt, ApiErrorExt, Core, RuntimeVersion, StorageProof, ProvideRuntimeApi, ApiRef};
25-
use sp_core::{testing::KeyStore, ExecutionContext, NativeOrEncoded};
24+
use sp_api::{ProvideRuntimeApi, ApiRef};
25+
use sp_core::testing::KeyStore;
2626
use sp_runtime::traits::{Zero, Block as BlockT, NumberFor};
2727
use substrate_test_runtime_client::runtime::Block;
2828

@@ -99,8 +99,7 @@ impl ProvideRuntimeApi<Block> for TestApi {
9999
fn runtime_api<'a>(&'a self) -> ApiRef<'a, Self::Api> {
100100
RuntimeApi {
101101
authorities: self.authorities.clone(),
102-
}
103-
.into()
102+
}.into()
104103
}
105104
}
106105

@@ -149,90 +148,13 @@ struct RuntimeApi {
149148
authorities: Vec<AuthorityId>,
150149
}
151150

152-
impl Core<Block> for RuntimeApi {
153-
fn Core_version_runtime_api_impl(
154-
&self,
155-
_: &BlockId<Block>,
156-
_: ExecutionContext,
157-
_: Option<()>,
158-
_: Vec<u8>,
159-
) -> std::result::Result<NativeOrEncoded<RuntimeVersion>, sp_blockchain::Error> {
160-
unimplemented!("Not required for testing!")
161-
}
162-
163-
fn Core_execute_block_runtime_api_impl(
164-
&self,
165-
_: &BlockId<Block>,
166-
_: ExecutionContext,
167-
_: Option<Block>,
168-
_: Vec<u8>,
169-
) -> std::result::Result<NativeOrEncoded<()>, sp_blockchain::Error> {
170-
unimplemented!("Not required for testing!")
171-
}
151+
sp_api::mock_impl_runtime_apis! {
152+
impl AuthorityDiscoveryApi<Block> for RuntimeApi {
153+
type Error = sp_blockchain::Error;
172154

173-
fn Core_initialize_block_runtime_api_impl(
174-
&self,
175-
_: &BlockId<Block>,
176-
_: ExecutionContext,
177-
_: Option<&<Block as BlockT>::Header>,
178-
_: Vec<u8>,
179-
) -> std::result::Result<NativeOrEncoded<()>, sp_blockchain::Error> {
180-
unimplemented!("Not required for testing!")
181-
}
182-
}
183-
184-
impl ApiErrorExt for RuntimeApi {
185-
type Error = sp_blockchain::Error;
186-
}
187-
188-
impl ApiExt<Block> for RuntimeApi {
189-
type StateBackend = <
190-
substrate_test_runtime_client::Backend as sc_client_api::backend::Backend<Block>
191-
>::State;
192-
193-
fn map_api_result<F: FnOnce(&Self) -> std::result::Result<R, E>, R, E>(
194-
&self,
195-
_: F
196-
) -> std::result::Result<R, E> {
197-
unimplemented!("Not required for testing!")
198-
}
199-
200-
fn runtime_version_at(
201-
&self,
202-
_: &BlockId<Block>,
203-
) -> std::result::Result<RuntimeVersion, Self::Error> {
204-
unimplemented!("Not required for testing!")
205-
}
206-
207-
fn record_proof(&mut self) {
208-
unimplemented!("Not required for testing!")
209-
}
210-
211-
fn extract_proof(&mut self) -> Option<StorageProof> {
212-
unimplemented!("Not required for testing!")
213-
}
214-
215-
fn into_storage_changes(
216-
&self,
217-
_: &Self::StateBackend,
218-
_: Option<&sp_api::ChangesTrieState<sp_api::HashFor<Block>, sp_api::NumberFor<Block>>>,
219-
_: <Block as sp_api::BlockT>::Hash,
220-
) -> std::result::Result<sp_api::StorageChanges<Self::StateBackend, Block>, String>
221-
where Self: Sized
222-
{
223-
unimplemented!("Not required for testing!")
224-
}
225-
}
226-
227-
impl AuthorityDiscoveryApi<Block> for RuntimeApi {
228-
fn AuthorityDiscoveryApi_authorities_runtime_api_impl(
229-
&self,
230-
_: &BlockId<Block>,
231-
_: ExecutionContext,
232-
_: Option<()>,
233-
_: Vec<u8>,
234-
) -> std::result::Result<NativeOrEncoded<Vec<AuthorityId>>, sp_blockchain::Error> {
235-
return Ok(NativeOrEncoded::Native(self.authorities.clone()));
155+
fn authorities(&self) -> Vec<AuthorityId> {
156+
self.authorities.clone()
157+
}
236158
}
237159
}
238160

client/finality-grandpa/src/tests.rs

+9-87
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,17 @@ use sp_keyring::Ed25519Keyring;
3030
use sc_client::LongestChain;
3131
use sc_client_api::backend::TransactionFor;
3232
use sp_blockchain::Result;
33-
use sp_api::{ApiRef, ApiErrorExt, Core, RuntimeVersion, ApiExt, StorageProof, ProvideRuntimeApi};
33+
use sp_api::{ApiRef, StorageProof, ProvideRuntimeApi};
3434
use substrate_test_runtime_client::runtime::BlockNumber;
3535
use sp_consensus::{
3636
BlockOrigin, ForkChoiceStrategy, ImportedAux, BlockImportParams, ImportResult, BlockImport,
3737
import_queue::{BoxJustificationImport, BoxFinalityProofImport},
3838
};
39-
use std::{
40-
collections::{HashMap, HashSet},
41-
result,
42-
pin::Pin,
43-
};
39+
use std::{collections::{HashMap, HashSet}, pin::Pin};
4440
use parity_scale_codec::Decode;
4541
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, HashFor};
4642
use sp_runtime::generic::{BlockId, DigestItem};
47-
use sp_core::{H256, NativeOrEncoded, ExecutionContext, crypto::Public};
43+
use sp_core::{H256, crypto::Public};
4844
use sp_finality_grandpa::{GRANDPA_ENGINE_ID, AuthorityList, GrandpaApi};
4945
use sp_state_machine::{InMemoryBackend, prove_read, read_proof_check};
5046

@@ -214,87 +210,13 @@ impl ProvideRuntimeApi<Block> for TestApi {
214210
}
215211
}
216212

217-
impl Core<Block> for RuntimeApi {
218-
fn Core_version_runtime_api_impl(
219-
&self,
220-
_: &BlockId<Block>,
221-
_: ExecutionContext,
222-
_: Option<()>,
223-
_: Vec<u8>,
224-
) -> Result<NativeOrEncoded<RuntimeVersion>> {
225-
unimplemented!("Not required for testing!")
226-
}
227-
228-
fn Core_execute_block_runtime_api_impl(
229-
&self,
230-
_: &BlockId<Block>,
231-
_: ExecutionContext,
232-
_: Option<Block>,
233-
_: Vec<u8>,
234-
) -> Result<NativeOrEncoded<()>> {
235-
unimplemented!("Not required for testing!")
236-
}
213+
sp_api::mock_impl_runtime_apis! {
214+
impl GrandpaApi<Block> for RuntimeApi {
215+
type Error = sp_blockchain::Error;
237216

238-
fn Core_initialize_block_runtime_api_impl(
239-
&self,
240-
_: &BlockId<Block>,
241-
_: ExecutionContext,
242-
_: Option<&<Block as BlockT>::Header>,
243-
_: Vec<u8>,
244-
) -> Result<NativeOrEncoded<()>> {
245-
unimplemented!("Not required for testing!")
246-
}
247-
}
248-
249-
impl ApiErrorExt for RuntimeApi {
250-
type Error = sp_blockchain::Error;
251-
}
252-
253-
impl ApiExt<Block> for RuntimeApi {
254-
type StateBackend = <
255-
substrate_test_runtime_client::Backend as sc_client_api::backend::Backend<Block>
256-
>::State;
257-
258-
fn map_api_result<F: FnOnce(&Self) -> result::Result<R, E>, R, E>(
259-
&self,
260-
_: F
261-
) -> result::Result<R, E> {
262-
unimplemented!("Not required for testing!")
263-
}
264-
265-
fn runtime_version_at(&self, _: &BlockId<Block>) -> Result<RuntimeVersion> {
266-
unimplemented!("Not required for testing!")
267-
}
268-
269-
fn record_proof(&mut self) {
270-
unimplemented!("Not required for testing!")
271-
}
272-
273-
fn extract_proof(&mut self) -> Option<StorageProof> {
274-
unimplemented!("Not required for testing!")
275-
}
276-
277-
fn into_storage_changes(
278-
&self,
279-
_: &Self::StateBackend,
280-
_: Option<&sp_api::ChangesTrieState<sp_api::HashFor<Block>, sp_api::NumberFor<Block>>>,
281-
_: <Block as sp_api::BlockT>::Hash,
282-
) -> std::result::Result<sp_api::StorageChanges<Self::StateBackend, Block>, String>
283-
where Self: Sized
284-
{
285-
unimplemented!("Not required for testing!")
286-
}
287-
}
288-
289-
impl GrandpaApi<Block> for RuntimeApi {
290-
fn GrandpaApi_grandpa_authorities_runtime_api_impl(
291-
&self,
292-
_: &BlockId<Block>,
293-
_: ExecutionContext,
294-
_: Option<()>,
295-
_: Vec<u8>,
296-
) -> Result<NativeOrEncoded<AuthorityList>> {
297-
Ok(self.inner.genesis_authorities.clone()).map(NativeOrEncoded::Native)
217+
fn grandpa_authorities(&self) -> AuthorityList {
218+
self.inner.genesis_authorities.clone()
219+
}
298220
}
299221
}
300222

primitives/api/proc-macro/src/decl_runtime_apis.rs

+11-5
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use crate::utils::{
1919
fold_fn_decl_for_client_side, extract_parameter_names_types_and_borrows,
2020
generate_native_call_generator_fn_name, return_type_extract_type,
2121
generate_method_runtime_api_impl_name, generate_call_api_at_fn_name, prefix_function_with_trait,
22-
replace_wild_card_parameter_names,
22+
replace_wild_card_parameter_names, AllowSelfRefInParameters,
2323
};
2424

2525
use proc_macro2::{TokenStream, Span};
@@ -198,7 +198,7 @@ fn generate_native_call_generators(decl: &ItemTrait) -> Result<TokenStream> {
198198

199199
// Generate a native call generator for each function of the given trait.
200200
for fn_ in fns {
201-
let params = extract_parameter_names_types_and_borrows(&fn_)?;
201+
let params = extract_parameter_names_types_and_borrows(&fn_, AllowSelfRefInParameters::No)?;
202202
let trait_fn_name = &fn_.ident;
203203
let fn_name = generate_native_call_generator_fn_name(&fn_.ident);
204204
let output = return_type_replace_block_with_node_block(fn_.output.clone());
@@ -592,7 +592,10 @@ impl<'a> ToClientSideDecl<'a> {
592592

593593
// Get types and if the value is borrowed from all parameters.
594594
// If there is an error, we push it as the block to the user.
595-
let param_types = match extract_parameter_names_types_and_borrows(fn_sig) {
595+
let param_types = match extract_parameter_names_types_and_borrows(
596+
fn_sig,
597+
AllowSelfRefInParameters::No,
598+
) {
596599
Ok(res) => res.into_iter().map(|v| {
597600
let ty = v.1;
598601
let borrow = v.2;
@@ -629,7 +632,10 @@ impl<'a> ToClientSideDecl<'a> {
629632
mut method: TraitItemMethod,
630633
context: TokenStream,
631634
) -> TraitItemMethod {
632-
let params = match extract_parameter_names_types_and_borrows(&method.sig) {
635+
let params = match extract_parameter_names_types_and_borrows(
636+
&method.sig,
637+
AllowSelfRefInParameters::No,
638+
) {
633639
Ok(res) => res.into_iter().map(|v| v.0).collect::<Vec<_>>(),
634640
Err(e) => {
635641
self.errors.push(e.to_compile_error());
@@ -780,7 +786,7 @@ fn generate_runtime_api_id(trait_name: &str) -> TokenStream {
780786
let mut res = [0; 8];
781787
res.copy_from_slice(blake2_rfc::blake2b::blake2b(8, &[], trait_name.as_bytes()).as_bytes());
782788

783-
quote!( const ID: [u8; 8] = [ #( #res ),* ]; )
789+
quote!( const ID: [u8; 8] = [ #( #res ),* ]; )
784790
}
785791

786792
/// Generates the const variable that holds the runtime api version.

0 commit comments

Comments
 (0)