sp_core/
testing.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Types that should only be used for testing!
19
20use crate::crypto::KeyTypeId;
21
22/// Key type for generic Ed25519 key.
23pub const ED25519: KeyTypeId = KeyTypeId(*b"ed25");
24/// Key type for generic Sr25519 key.
25pub const SR25519: KeyTypeId = KeyTypeId(*b"sr25");
26/// Key type for generic ECDSA key.
27pub const ECDSA: KeyTypeId = KeyTypeId(*b"ecds");
28/// Key type for generic Bandersnatch key.
29pub const BANDERSNATCH: KeyTypeId = KeyTypeId(*b"band");
30/// Key type for generic BLS12-377 key.
31pub const BLS377: KeyTypeId = KeyTypeId(*b"bls7");
32/// Key type for generic BLS12-381 key.
33pub const BLS381: KeyTypeId = KeyTypeId(*b"bls8");
34/// Key type for (ECDSA,BLS12-377) key pair
35pub const ECDSA_BLS377: KeyTypeId = KeyTypeId(*b"ecb7");
36/// Key type for (ECDSA,BLS12-381) key pair
37pub const ECDSA_BLS381: KeyTypeId = KeyTypeId(*b"ecb8");
38
39/// Macro for exporting functions from wasm in with the expected signature for using it with the
40/// wasm executor. This is useful for tests where you need to call a function in wasm.
41///
42/// The input parameters are expected to be SCALE encoded and will be automatically decoded for you.
43/// The output value is also SCALE encoded when returned back to the host.
44///
45/// The functions are feature-gated with `#[cfg(not(feature = "std"))]`, so they are only available
46/// from within wasm.
47///
48/// # Example
49///
50/// ```
51/// # use sp_core::wasm_export_functions;
52///
53/// wasm_export_functions! {
54///     fn test_in_wasm(value: bool, another_value: Vec<u8>) -> bool {
55///         value && another_value.is_empty()
56///     }
57///
58///     fn without_return_value() {
59///         // do something
60///     }
61/// }
62/// ```
63#[macro_export]
64macro_rules! wasm_export_functions {
65	(
66		$(
67			fn $name:ident (
68				$( $arg_name:ident: $arg_ty:ty ),* $(,)?
69			) $( -> $ret_ty:ty )? { $( $fn_impl:tt )* }
70		)*
71	) => {
72		$(
73			$crate::wasm_export_functions! {
74				@IMPL
75				fn $name (
76					$( $arg_name: $arg_ty ),*
77				) $( -> $ret_ty )? { $( $fn_impl )* }
78			}
79		)*
80	};
81	(@IMPL
82		fn $name:ident (
83				$( $arg_name:ident: $arg_ty:ty ),*
84		) { $( $fn_impl:tt )* }
85	) => {
86		#[no_mangle]
87		#[allow(unreachable_code)]
88		#[cfg(not(feature = "std"))]
89		pub fn $name(input_data: *mut u8, input_len: usize) -> u64 {
90			let input: &[u8] = if input_len == 0 {
91				&[0u8; 0]
92			} else {
93				unsafe {
94					::core::slice::from_raw_parts(input_data, input_len)
95				}
96			};
97
98			{
99				let ($( $arg_name ),*) : ($( $arg_ty ),*) = $crate::Decode::decode(
100					&mut &input[..],
101				).expect("Input data is correctly encoded");
102
103				(|| { $( $fn_impl )* })()
104			}
105
106			$crate::to_substrate_wasm_fn_return_value(&())
107		}
108	};
109	(@IMPL
110		fn $name:ident (
111				$( $arg_name:ident: $arg_ty:ty ),*
112		) $( -> $ret_ty:ty )? { $( $fn_impl:tt )* }
113	) => {
114		#[no_mangle]
115		#[allow(unreachable_code)]
116		#[cfg(not(feature = "std"))]
117		pub fn $name(input_data: *mut u8, input_len: usize) -> u64 {
118			let input: &[u8] = if input_len == 0 {
119				&[0u8; 0]
120			} else {
121				unsafe {
122					::core::slice::from_raw_parts(input_data, input_len)
123				}
124			};
125
126			let output $( : $ret_ty )? = {
127				let ($( $arg_name ),*) : ($( $arg_ty ),*) = $crate::Decode::decode(
128					&mut &input[..],
129				).expect("Input data is correctly encoded");
130
131				(|| { $( $fn_impl )* })()
132			};
133
134			$crate::to_substrate_wasm_fn_return_value(&output)
135		}
136	};
137}
138
139/// A task executor that can be used in tests.
140///
141/// Internally this just wraps a `ThreadPool` with a pool size of `8`. This
142/// should ensure that we have enough threads in tests for spawning blocking futures.
143#[cfg(feature = "std")]
144#[derive(Clone)]
145pub struct TaskExecutor(futures::executor::ThreadPool);
146
147#[cfg(feature = "std")]
148impl TaskExecutor {
149	/// Create a new instance of `Self`.
150	pub fn new() -> Self {
151		let mut builder = futures::executor::ThreadPoolBuilder::new();
152		Self(builder.pool_size(8).create().expect("Failed to create thread pool"))
153	}
154}
155
156#[cfg(feature = "std")]
157impl Default for TaskExecutor {
158	fn default() -> Self {
159		Self::new()
160	}
161}
162
163#[cfg(feature = "std")]
164impl crate::traits::SpawnNamed for TaskExecutor {
165	fn spawn_blocking(
166		&self,
167		_name: &'static str,
168		_group: Option<&'static str>,
169		future: futures::future::BoxFuture<'static, ()>,
170	) {
171		self.0.spawn_ok(future);
172	}
173	fn spawn(
174		&self,
175		_name: &'static str,
176		_group: Option<&'static str>,
177		future: futures::future::BoxFuture<'static, ()>,
178	) {
179		self.0.spawn_ok(future);
180	}
181}
182
183#[cfg(feature = "std")]
184impl crate::traits::SpawnEssentialNamed for TaskExecutor {
185	fn spawn_essential_blocking(
186		&self,
187		_: &'static str,
188		_: Option<&'static str>,
189		future: futures::future::BoxFuture<'static, ()>,
190	) {
191		self.0.spawn_ok(future);
192	}
193	fn spawn_essential(
194		&self,
195		_: &'static str,
196		_: Option<&'static str>,
197		future: futures::future::BoxFuture<'static, ()>,
198	) {
199		self.0.spawn_ok(future);
200	}
201}