diff --git a/Cargo.lock b/Cargo.lock index 128b54e7c6d6a..9ebfa3d308fc2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6436,12 +6436,12 @@ name = "remote-externalities" version = "0.9.0" dependencies = [ "async-std", - "bincode", "env_logger 0.8.2", - "futures 0.1.30", + "futures 0.3.12", "hex-literal", "jsonrpc-core-client", "log", + "parity-scale-codec", "sc-rpc", "sc-rpc-api", "sp-core", diff --git a/bin/node/cli/src/command.rs b/bin/node/cli/src/command.rs index d3689bdcd6743..ece97436bfdf4 100644 --- a/bin/node/cli/src/command.rs +++ b/bin/node/cli/src/command.rs @@ -159,7 +159,7 @@ pub fn run() -> Result<()> { let task_manager = sc_service::TaskManager::new( config.task_executor.clone(), registry, - ).unwrap(); + ).map_err(|e| sc_cli::Error::Service(sc_service::Error::Prometheus(e)))?; Ok((cmd.run::(config), task_manager)) }) diff --git a/frame/support/procedural/src/lib.rs b/frame/support/procedural/src/lib.rs index 2c2cdf00a0453..e64a364d2951e 100644 --- a/frame/support/procedural/src/lib.rs +++ b/frame/support/procedural/src/lib.rs @@ -17,7 +17,7 @@ //! Proc macro of Support code for the runtime. -#![recursion_limit="512"] +#![recursion_limit = "512"] mod storage; mod construct_runtime; diff --git a/frame/support/src/dispatch.rs b/frame/support/src/dispatch.rs index f5c8f017e3451..c2315e66e3239 100644 --- a/frame/support/src/dispatch.rs +++ b/frame/support/src/dispatch.rs @@ -80,18 +80,18 @@ impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug {} /// // FRAME pallets. /// #[weight = 0] /// fn my_function(origin, var: u64) -> dispatch::DispatchResult { -/// // Your implementation -/// Ok(()) +/// // Your implementation +/// Ok(()) /// } /// -/// // Public functions are both dispatchable and available to other +/// // Public functions are both dispatchable and available to other /// // FRAME pallets. /// #[weight = 0] -/// pub fn my_public_function(origin) -> dispatch::DispatchResult { +/// pub fn my_public_function(origin) -> dispatch::DispatchResult { /// // Your implementation -/// Ok(()) +/// Ok(()) +/// } /// } -/// } /// } /// # fn main() {} /// ``` @@ -99,8 +99,10 @@ impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug {} /// The declaration is set with the header where: /// /// * `Module`: The struct generated by the macro, with type `Config`. -/// * `Call`: The enum generated for every pallet, which implements [`Callable`](./dispatch/trait.Callable.html). -/// * `origin`: Alias of `T::Origin`, declared by the [`impl_outer_origin!`](./macro.impl_outer_origin.html) macro. +/// * `Call`: The enum generated for every pallet, which implements +/// [`Callable`](./dispatch/trait.Callable.html). +/// * `origin`: Alias of `T::Origin`, declared by the +/// [`impl_outer_origin!`](./macro.impl_outer_origin.html) macro. /// * `Result`: The expected return type from pallet functions. /// /// The first parameter of dispatchable functions must always be `origin`. @@ -119,15 +121,15 @@ impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug {} /// pub struct Module for enum Call where origin: T::Origin { /// #[weight = 0] /// fn my_long_function(origin) -> dispatch::DispatchResult { -/// // Your implementation +/// // Your implementation /// Ok(()) /// } /// /// #[weight = 0] /// fn my_short_function(origin) { -/// // Your implementation +/// // Your implementation +/// } /// } -/// } /// } /// # fn main() {} /// ``` @@ -184,7 +186,7 @@ impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug {} /// #[weight = 0] /// #[transactional] /// fn my_short_function(origin) { -/// // Your implementation +/// // Your implementation /// } /// } /// } @@ -203,12 +205,12 @@ impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug {} /// decl_module! { /// pub struct Module for enum Call where origin: T::Origin { /// #[weight = 0] -/// fn my_privileged_function(origin) -> dispatch::DispatchResult { +/// fn my_privileged_function(origin) -> dispatch::DispatchResult { /// ensure_root(origin)?; -/// // Your implementation +/// // Your implementation /// Ok(()) /// } -/// } +/// } /// } /// # fn main() {} /// ``` @@ -218,15 +220,17 @@ impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug {} /// Attributes on functions are supported, but must be in the order of: /// 1. Optional #\[doc\] attribute. /// 2. #\[weight\] attribute. -/// 3. Optional function attributes, for instance #\[transactional\]. Those function attributes will be written -/// only on the dispatchable functions implemented on `Module`, not on the `Call` enum variant. +/// 3. Optional function attributes, for instance #\[transactional\]. Those function attributes will +/// be written only on the dispatchable functions implemented on `Module`, not on the `Call` enum +/// variant. /// /// ## Multiple Module Instances Example /// -/// A Substrate module can be built such that multiple instances of the same module can be used within a single -/// runtime. For example, the [Balances module](../pallet_balances/index.html) can be added multiple times to your -/// runtime in order to support multiple, independent currencies for your blockchain. Here is an example of how -/// you would declare such a module using the `decl_module!` macro: +/// A Substrate module can be built such that multiple instances of the same module can be used +/// within a single runtime. For example, the [Balances module](../pallet_balances/index.html) can +/// be added multiple times to your runtime in order to support multiple, independent currencies for +/// your blockchain. Here is an example of how you would declare such a module using the +/// `decl_module!` macro: /// /// ``` /// # #[macro_use] @@ -251,10 +255,10 @@ impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug {} /// /// ## Where clause /// -/// Besides the default `origin: T::Origin`, you can also pass other bounds to the module declaration. -/// This where bound will be replicated to all types generated by this macro. The chaining of multiple -/// trait bounds with `+` is not supported. If multiple bounds for one type are required, it needs to -/// be split up into multiple bounds. +/// Besides the default `origin: T::Origin`, you can also pass other bounds to the module +/// declaration. This where bound will be replicated to all types generated by this macro. The +/// chaining of multiple trait bounds with `+` is not supported. If multiple bounds for one type are +/// required, it needs to be split up into multiple bounds. /// /// ``` /// # #[macro_use] @@ -276,16 +280,18 @@ impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug {} /// The following are reserved function signatures: /// /// * `deposit_event`: Helper function for depositing an [event](https://docs.substrate.dev/docs/event-enum). -/// The default behavior is to call `deposit_event` from the [System module](../frame_system/index.html). -/// However, you can write your own implementation for events in your runtime. To use the default behavior, -/// add `fn deposit_event() = default;` to your `Module`. +/// The default behavior is to call `deposit_event` from the [System +/// module](../frame_system/index.html). However, you can write your own implementation for events +/// in your runtime. To use the default behavior, add `fn deposit_event() = default;` to your +/// `Module`. /// -/// The following reserved functions also take the block number (with type `T::BlockNumber`) as an optional input: +/// The following reserved functions also take the block number (with type `T::BlockNumber`) as an +/// optional input: /// /// * `on_runtime_upgrade`: Executes at the beginning of a block prior to on_initialize when there -/// is a runtime upgrade. This allows each module to upgrade its storage before the storage items are used. -/// As such, **calling other modules must be avoided**!! Using this function will implement the -/// [`OnRuntimeUpgrade`](../sp_runtime/traits/trait.OnRuntimeUpgrade.html) trait. +/// is a runtime upgrade. This allows each module to upgrade its storage before the storage items +/// are used. As such, **calling other modules must be avoided**!! Using this function will +/// implement the [`OnRuntimeUpgrade`](../sp_runtime/traits/trait.OnRuntimeUpgrade.html) trait. /// Function signature must be `fn on_runtime_upgrade() -> frame_support::weights::Weight`. /// /// * `on_initialize`: Executes at the beginning of a block. Using this function will @@ -300,11 +306,11 @@ impl Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug {} /// * `fn on_finalize(n: BlockNumber) -> frame_support::weights::Weight` or /// * `fn on_finalize() -> frame_support::weights::Weight` /// -/// * `offchain_worker`: Executes at the beginning of a block and produces extrinsics for a future block -/// upon completion. Using this function will implement the +/// * `offchain_worker`: Executes at the beginning of a block and produces extrinsics for a future +/// block upon completion. Using this function will implement the /// [`OffchainWorker`](./traits/trait.OffchainWorker.html) trait. -/// * `integrity_test`: Executes in a test generated by `construct_runtime`, note it doesn't -/// execute in an externalities-provided environment. Implement +/// * `integrity_test`: Executes in a test generated by `construct_runtime`, note it doesn't execute +/// in an externalities-provided environment. Implement /// [`IntegrityTest`](./trait.IntegrityTest.html) trait. #[macro_export] macro_rules! decl_module { @@ -1325,13 +1331,27 @@ macro_rules! decl_module { $crate::sp_tracing::enter_span!($crate::sp_tracing::trace_span!("on_runtime_upgrade")); let result: $return = (|| { $( $impl )* })(); - $crate::crate_to_pallet_version!() + let new_storage_version = $crate::crate_to_pallet_version!(); + new_storage_version .put_into_storage::<<$trait_instance as $system::Config>::PalletInfo, Self>(); let additional_write = < <$trait_instance as $system::Config>::DbWeight as $crate::traits::Get<_> >::get().writes(1); + let pallet_name = << + $trait_instance + as + $system::Config + >::PalletInfo as $crate::traits::PalletInfo>::name::().expect("pallet will have name in the runtime; qed"); + + $crate::debug::info!( + target: $crate::LOG_TARGET, + "⚠️ running migration for {} and setting new storage version to {:?}", + pallet_name, + new_storage_version, + ); + result.saturating_add(additional_write) } @@ -1359,9 +1379,23 @@ macro_rules! decl_module { fn on_runtime_upgrade() -> $crate::dispatch::Weight { $crate::sp_tracing::enter_span!($crate::sp_tracing::trace_span!("on_runtime_upgrade")); - $crate::crate_to_pallet_version!() + let new_storage_version = $crate::crate_to_pallet_version!(); + new_storage_version .put_into_storage::<<$trait_instance as $system::Config>::PalletInfo, Self>(); + let pallet_name = << + $trait_instance + as + $system::Config + >::PalletInfo as $crate::traits::PalletInfo>::name::().expect("pallet will have name in the runtime; qed"); + + $crate::debug::info!( + target: $crate::LOG_TARGET, + "✅ no migration for '{}' and setting new storage version to {:?}", + pallet_name, + new_storage_version, + ); + < <$trait_instance as $system::Config>::DbWeight as $crate::traits::Get<_> >::get().writes(1) diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index e7af1ccab68fd..e16200ef0b99e 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -80,6 +80,9 @@ pub use self::storage::{ pub use self::dispatch::{Parameter, Callable}; pub use sp_runtime::{self, ConsensusEngineId, print, traits::Printable}; +/// A unified log target for support operations. +pub const LOG_TARGET: &'static str = "runtime::frame-support"; + /// A type that cannot be instantiated. #[derive(Debug, PartialEq, Eq, Clone)] pub enum Never {} diff --git a/frame/support/src/traits.rs b/frame/support/src/traits.rs index f0ab3be642cbe..395a23d581e6b 100644 --- a/frame/support/src/traits.rs +++ b/frame/support/src/traits.rs @@ -1553,6 +1553,54 @@ pub trait OnGenesis { fn on_genesis() {} } +/// Prefix to be used (optionally) for implementing [`OnRuntimeUpgrade::storage_key`]. +#[cfg(feature = "try-runtime")] +pub const ON_RUNTIME_UPGRADE_PREFIX: &[u8] = b"__ON_RUNTIME_UPGRADE__"; + +/// Some helper functions for [`OnRuntimeUpgrade`] during `try-runtime` testing. +#[cfg(feature = "try-runtime")] +pub trait OnRuntimeUpgradeHelpersExt { + /// Generate a storage key unique to this runtime upgrade. + /// + /// This can be used to communicate data from pre-upgrade to post-upgrade state and check + /// them. See [`set_temp_storage`] and [`get_temp_storage`]. + #[cfg(feature = "try-runtime")] + fn storage_key(ident: &str) -> [u8; 32] { + let prefix = sp_io::hashing::twox_128(ON_RUNTIME_UPGRADE_PREFIX); + let ident = sp_io::hashing::twox_128(ident.as_bytes()); + + let mut final_key = [0u8; 32]; + final_key[..16].copy_from_slice(&prefix); + final_key[16..].copy_from_slice(&ident); + + final_key + } + + /// Get temporary storage data written by [`set_temp_storage`]. + /// + /// Returns `None` if either the data is unavailable or un-decodable. + /// + /// A `at` storage identifier must be provided to indicate where the storage is being read from. + #[cfg(feature = "try-runtime")] + fn get_temp_storage(at: &str) -> Option { + sp_io::storage::get(&Self::storage_key(at)) + .and_then(|bytes| Decode::decode(&mut &*bytes).ok()) + } + + /// Write some temporary data to a specific storage that can be read (potentially in + /// post-upgrade hook) via [`get_temp_storage`]. + /// + /// A `at` storage identifier must be provided to indicate where the storage is being written + /// to. + #[cfg(feature = "try-runtime")] + fn set_temp_storage(data: T, at: &str) { + sp_io::storage::set(&Self::storage_key(at), &data.encode()); + } +} + +#[cfg(feature = "try-runtime")] +impl OnRuntimeUpgradeHelpersExt for U {} + /// The runtime upgrade trait. /// /// Implementing this lets you express what should happen when the runtime upgrades, diff --git a/primitives/storage/src/lib.rs b/primitives/storage/src/lib.rs index 1016b73eb1e3b..ced8d8c02a80b 100644 --- a/primitives/storage/src/lib.rs +++ b/primitives/storage/src/lib.rs @@ -29,7 +29,7 @@ use codec::{Encode, Decode}; /// Storage key. #[derive(PartialEq, Eq, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash, PartialOrd, Ord, Clone))] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash, PartialOrd, Ord, Clone, Encode, Decode))] pub struct StorageKey( #[cfg_attr(feature = "std", serde(with = "impl_serde::serialize"))] pub Vec, ); @@ -107,7 +107,7 @@ impl PrefixedStorageKey { /// Storage data associated to a [`StorageKey`]. #[derive(PartialEq, Eq, RuntimeDebug)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash, PartialOrd, Ord, Clone))] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash, PartialOrd, Ord, Clone, Encode, Decode))] pub struct StorageData( #[cfg_attr(feature = "std", serde(with="impl_serde::serialize"))] pub Vec, diff --git a/utils/frame/remote-externalities/Cargo.toml b/utils/frame/remote-externalities/Cargo.toml index 41a3b26217860..d4825211d8a66 100644 --- a/utils/frame/remote-externalities/Cargo.toml +++ b/utils/frame/remote-externalities/Cargo.toml @@ -16,12 +16,12 @@ targets = ["x86_64-unknown-linux-gnu"] jsonrpc-core-client = { version = "15.1.0", features = ["http"] } sc-rpc-api = { version = "0.9.0", path = "../../../client/rpc-api" } sc-rpc = { version = "3.0.0", path = "../../../client/rpc" } -futures = "0.1.29" +futures = "0.3" hex-literal = "0.3.1" env_logger = "0.8.2" log = "0.4.11" -bincode = "1.3.1" +codec = { package = "parity-scale-codec", version = "2.0.0" } tokio = "0.1.22" sp-io = { version = "3.0.0", path = "../../../primitives/io" } diff --git a/utils/frame/remote-externalities/proxy_test b/utils/frame/remote-externalities/proxy_test deleted file mode 100644 index adb93f5ba270c..0000000000000 Binary files a/utils/frame/remote-externalities/proxy_test and /dev/null differ diff --git a/utils/frame/remote-externalities/src/lib.rs b/utils/frame/remote-externalities/src/lib.rs index 6c8b49c7c85d5..ab26226253858 100644 --- a/utils/frame/remote-externalities/src/lib.rs +++ b/utils/frame/remote-externalities/src/lib.rs @@ -112,7 +112,11 @@ use sp_core::{ hexdisplay::HexDisplay, storage::{StorageKey, StorageData}, }; -use futures::future::Future; +use futures::{ + compat::Future01CompatExt, + TryFutureExt, +}; +use codec::{Encode, Decode}; type KeyPair = (StorageKey, StorageData); type Number = u32; @@ -192,7 +196,6 @@ impl CacheConfig { pub struct Builder { inject: Vec, mode: Mode, - chain: String, } impl Default for Builder { @@ -205,7 +208,6 @@ impl Default for Builder { cache: None, modules: Default::default(), }), - chain: "UNSET".into(), } } } @@ -229,74 +231,71 @@ impl Builder { // RPC methods impl Builder { - async fn rpc_get_head(&self) -> Hash { - let mut rt = tokio::runtime::Runtime::new().expect("Unable to create a runtime"); + async fn rpc_get_head(&self) -> Result { let uri = self.as_online().uri.clone(); - rt.block_on::<_, _, ()>(futures::lazy(move || { - trace!(target: LOG_TARGET, "rpc: finalized_head"); - let client: sc_rpc_api::chain::ChainClient = - jsonrpc_core_client::transports::http::connect(&uri).wait().unwrap(); - Ok(client.finalized_head().wait().unwrap()) - })) - .unwrap() + trace!(target: LOG_TARGET, "rpc: finalized_head"); + let client: sc_rpc_api::chain::ChainClient = + jsonrpc_core_client::transports::http::connect(&uri) + .compat() + .map_err(|_| "client initialization failed") + .await?; + client.finalized_head().compat().map_err(|_| "rpc finalized_head failed.").await } /// Relay the request to `state_getPairs` rpc endpoint. /// /// Note that this is an unsafe RPC. - async fn rpc_get_pairs(&self, prefix: StorageKey, at: Hash) -> Vec { - let mut rt = tokio::runtime::Runtime::new().expect("Unable to create a runtime"); - let uri = self.as_online().uri.clone(); - rt.block_on::<_, _, ()>(futures::lazy(move || { - trace!(target: LOG_TARGET, "rpc: storage_pairs: {:?} / {:?}", prefix, at); - let client: sc_rpc_api::state::StateClient = - jsonrpc_core_client::transports::http::connect(&uri).wait().unwrap(); - Ok(client.storage_pairs(prefix, Some(at)).wait().unwrap()) - })) - .unwrap() - } - - /// Get the chain name. - async fn chain_name(&self) -> String { - let mut rt = tokio::runtime::Runtime::new().expect("Unable to create a runtime"); + async fn rpc_get_pairs( + &self, + prefix: StorageKey, + at: Hash, + ) -> Result, &'static str> { let uri = self.as_online().uri.clone(); - rt.block_on::<_, _, ()>(futures::lazy(move || { - trace!(target: LOG_TARGET, "rpc: system_chain"); - let client: sc_rpc_api::system::SystemClient<(), ()> = - jsonrpc_core_client::transports::http::connect(&uri).wait().unwrap(); - Ok(client.system_chain().wait().unwrap()) - })) - .unwrap() + trace!(target: LOG_TARGET, "rpc: storage_pairs: {:?} / {:?}", prefix, at); + let client: sc_rpc_api::state::StateClient = + jsonrpc_core_client::transports::http::connect(&uri) + .compat() + .map_err(|_| "client initialization failed") + .await?; + client + .storage_pairs(prefix, Some(at)) + .compat() + .map_err(|_| "rpc finalized_head failed.") + .await } } // Internal methods impl Builder { /// Save the given data as cache. - fn save_cache(&self, data: &[KeyPair], path: &Path) { - let bdata = bincode::serialize(data).unwrap(); + fn save_cache(&self, data: &[KeyPair], path: &Path) -> Result<(), &'static str> { info!(target: LOG_TARGET, "writing to cache file {:?}", path); - fs::write(path, bdata).unwrap(); + fs::write(path, data.encode()).map_err(|_| "fs::write failed.")?; + Ok(()) } /// initialize `Self` from cache. Panics if the file does not exist. - fn load_cache(&self, path: &Path) -> Vec { + fn load_cache(&self, path: &Path) -> Result, &'static str> { info!(target: LOG_TARGET, "scraping keypairs from cache {:?}", path,); - let bytes = fs::read(path).unwrap(); - bincode::deserialize(&bytes[..]).unwrap() + let bytes = fs::read(path).map_err(|_| "fs::read failed.")?; + Decode::decode(&mut &*bytes).map_err(|_| "decode failed") } /// Build `Self` from a network node denoted by `uri`. - async fn load_remote(&self) -> Vec { + async fn load_remote(&self) -> Result, &'static str> { let config = self.as_online(); - let at = self.as_online().at.unwrap().clone(); + let at = self + .as_online() + .at + .expect("online config must be initialized by this point; qed.") + .clone(); info!(target: LOG_TARGET, "scraping keypairs from remote node {} @ {:?}", config.uri, at); let keys_and_values = if config.modules.len() > 0 { let mut filtered_kv = vec![]; for f in config.modules.iter() { let hashed_prefix = StorageKey(twox_128(f.as_bytes()).to_vec()); - let module_kv = self.rpc_get_pairs(hashed_prefix.clone(), at).await; + let module_kv = self.rpc_get_pairs(hashed_prefix.clone(), at).await?; info!( target: LOG_TARGET, "downloaded data for module {} (count: {} / prefix: {:?}).", @@ -309,25 +308,26 @@ impl Builder { filtered_kv } else { info!(target: LOG_TARGET, "downloading data for all modules."); - self.rpc_get_pairs(StorageKey(vec![]), at).await.into_iter().collect::>() + self.rpc_get_pairs(StorageKey(vec![]), at).await?.into_iter().collect::>() }; - keys_and_values + Ok(keys_and_values) } - async fn init_remote_client(&mut self) { - self.as_online_mut().at = Some(self.rpc_get_head().await); - self.chain = self.chain_name().await; + async fn init_remote_client(&mut self) -> Result<(), &'static str> { + let at = self.rpc_get_head().await?; + self.as_online_mut().at = Some(at); + Ok(()) } - async fn pre_build(mut self) -> Vec { + async fn pre_build(mut self) -> Result, &'static str> { let mut base_kv = match self.mode.clone() { - Mode::Offline(config) => self.load_cache(&config.cache.path()), + Mode::Offline(config) => self.load_cache(&config.cache.path())?, Mode::Online(config) => { - self.init_remote_client().await; - let kp = self.load_remote().await; + self.init_remote_client().await?; + let kp = self.load_remote().await?; if let Some(c) = config.cache { - self.save_cache(&kp, &c.path()); + self.save_cache(&kp, &c.path())?; } kp } @@ -339,7 +339,7 @@ impl Builder { self.inject.len() ); base_kv.extend(self.inject.clone()); - base_kv + Ok(base_kv) } } @@ -365,8 +365,8 @@ impl Builder { } /// Build the test externalities. - pub async fn build(self) -> TestExternalities { - let kv = self.pre_build().await; + pub async fn build(self) -> Result { + let kv = self.pre_build().await?; let mut ext = TestExternalities::new_empty(); info!(target: LOG_TARGET, "injecting a total of {} keys", kv.len()); @@ -374,10 +374,11 @@ impl Builder { let (k, v) = (k.0, v.0); ext.insert(k, v); } - ext + Ok(ext) } } +#[cfg(feature = "remote-test")] #[cfg(test)] mod tests { use super::*; @@ -390,7 +391,6 @@ mod tests { } #[async_std::test] - #[cfg(feature = "remote-test")] async fn can_build_one_pallet() { init_logger(); Builder::new() @@ -400,6 +400,7 @@ mod tests { })) .build() .await + .unwrap() .execute_with(|| {}); } @@ -412,11 +413,11 @@ mod tests { })) .build() .await + .unwrap() .execute_with(|| {}); } #[async_std::test] - #[cfg(feature = "remote-test")] async fn can_create_cache() { init_logger(); Builder::new() @@ -429,6 +430,7 @@ mod tests { })) .build() .await + .unwrap() .execute_with(|| {}); let to_delete = std::fs::read_dir(CacheConfig::default().directory) @@ -446,9 +448,8 @@ mod tests { } #[async_std::test] - #[cfg(feature = "remote-test")] async fn can_build_all() { init_logger(); - Builder::new().build().await.execute_with(|| {}); + Builder::new().build().await.unwrap().execute_with(|| {}); } } diff --git a/utils/frame/try-runtime/cli/src/lib.rs b/utils/frame/try-runtime/cli/src/lib.rs index 92526379f471e..4ab38692a5cfa 100644 --- a/utils/frame/try-runtime/cli/src/lib.rs +++ b/utils/frame/try-runtime/cli/src/lib.rs @@ -133,7 +133,7 @@ impl TryRuntimeCmd { }; // inject the code into this ext. - builder.inject(&[(code_key, code)]).build().await + builder.inject(&[(code_key, code)]).build().await? }; let encoded_result = StateMachine::<_, _, NumberFor, _>::new(