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

Fix try-runtime follow-chain, try-runtime upgrade tuple tests, cli test utils #13794

Merged
merged 31 commits into from
Apr 6, 2023
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
cf0874d
new test for try-runtime tuple stuff
kianenigma Mar 31, 2023
b62c68c
fix
kianenigma Mar 31, 2023
7ccae6c
Merge branch 'master' of github.com:paritytech/substrate into liam-fi…
liamaharon Mar 31, 2023
d1ac703
remove development comment
liamaharon Mar 31, 2023
e826168
formatting
liamaharon Mar 31, 2023
cfd0dd7
remove todo comment
liamaharon Apr 1, 2023
d5d58bc
follow-chain working test
liamaharon Apr 4, 2023
8094ba8
refactor common cli testing utils
liamaharon Apr 4, 2023
b2ad590
fix comment
liamaharon Apr 4, 2023
f644dfa
revert Cargo.lock changes
liamaharon Apr 4, 2023
b9a6eba
update Cargo.lock
liamaharon Apr 4, 2023
90f135e
improve doc comment
liamaharon Apr 4, 2023
00aa83b
fix error typo
liamaharon Apr 4, 2023
cd56330
Merge branch 'master' of github.com:paritytech/substrate into liam-fi…
liamaharon Apr 4, 2023
0f79142
update Cargo.lock
liamaharon Apr 4, 2023
44b456b
feature gate try-runtime test
liamaharon Apr 5, 2023
38dee61
build_substrate cli test util
liamaharon Apr 5, 2023
5532ee6
feature gate follow_chain tests
liamaharon Apr 5, 2023
3ca75d3
move fn start_node to test-utils
liamaharon Apr 5, 2023
2a6d812
improve test pkg name
liamaharon Apr 5, 2023
7b3ca6f
use tokio Child and Command
liamaharon Apr 5, 2023
a1907b3
Merge branch 'master' of github.com:paritytech/substrate into liam-fi…
liamaharon Apr 5, 2023
391b741
remove redundant import
liamaharon Apr 5, 2023
99e23ae
fix ci
liamaharon Apr 5, 2023
b122fe6
Merge branch 'master' of github.com:paritytech/substrate into liam-fi…
liamaharon Apr 5, 2023
28dab86
fix ci
liamaharon Apr 5, 2023
ffeb781
don't leave hanging processes
liamaharon Apr 5, 2023
99c62a7
improved child process cleanup
liamaharon Apr 5, 2023
8c351c2
use existing KillChildOnDrop
liamaharon Apr 5, 2023
10a7b9e
remove redundant comment
liamaharon Apr 5, 2023
a01da35
Update test-utils/cli/src/lib.rs
liamaharon Apr 6, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
317 changes: 202 additions & 115 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions bin/node/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ tokio-util = { version = "0.7.4", features = ["compat"] }
wait-timeout = "0.2"
substrate-rpc-client = { path = "../../../utils/frame/rpc/client" }
pallet-timestamp = { version = "4.0.0-dev", path = "../../../frame/timestamp" }
substrate-cli-test-utils = { path = "../../../test-utils/cli" }

[build-dependencies]
clap = { version = "4.0.9", optional = true }
Expand Down
2 changes: 1 addition & 1 deletion bin/node/cli/tests/benchmark_block_works.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use assert_cmd::cargo::cargo_bin;
use std::process::Command;
use tempfile::tempdir;

pub mod common;
use substrate_cli_test_utils as common;

/// `benchmark block` works for the dev runtime using the wasm executor.
#[tokio::test]
Expand Down
2 changes: 0 additions & 2 deletions bin/node/cli/tests/benchmark_pallet_works.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
use assert_cmd::cargo::cargo_bin;
use std::process::Command;

pub mod common;

/// `benchmark pallet` works for the different combinations of `steps` and `repeat`.
#[test]
fn benchmark_pallet_works() {
Expand Down
2 changes: 1 addition & 1 deletion bin/node/cli/tests/check_block_works.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use assert_cmd::cargo::cargo_bin;
use std::process::Command;
use tempfile::tempdir;

pub mod common;
use substrate_cli_test_utils as common;

#[tokio::test]
async fn check_block_works() {
Expand Down
2 changes: 1 addition & 1 deletion bin/node/cli/tests/export_import_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use regex::Regex;
use std::{fs, path::PathBuf, process::Command};
use tempfile::{tempdir, TempDir};

pub mod common;
use substrate_cli_test_utils as common;

fn contains_error(logged_output: &str) -> bool {
logged_output.contains("Error")
Expand Down
2 changes: 1 addition & 1 deletion bin/node/cli/tests/inspect_works.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use assert_cmd::cargo::cargo_bin;
use std::process::Command;
use tempfile::tempdir;

pub mod common;
use substrate_cli_test_utils as common;

#[tokio::test]
async fn inspect_works() {
Expand Down
2 changes: 1 addition & 1 deletion bin/node/cli/tests/purge_chain_works.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use assert_cmd::cargo::cargo_bin;
use std::process::Command;
use tempfile::tempdir;

pub mod common;
use substrate_cli_test_utils as common;

#[tokio::test]
#[cfg(unix)]
Expand Down
2 changes: 1 addition & 1 deletion bin/node/cli/tests/remember_state_pruning_works.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

use tempfile::tempdir;

pub mod common;
use substrate_cli_test_utils as common;

#[tokio::test]
#[cfg(unix)]
Expand Down
17 changes: 4 additions & 13 deletions bin/node/cli/tests/running_the_node_and_interrupt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@
use assert_cmd::cargo::cargo_bin;
use nix::sys::signal::Signal::{self, SIGINT, SIGTERM};
use std::{
process::{self, Child, Command},
process::{self, Command},
time::Duration,
};
use tempfile::tempdir;

pub mod common;
use substrate_cli_test_utils as common;

#[tokio::test]
async fn running_the_node_works_and_can_be_interrupted() {
Expand Down Expand Up @@ -71,17 +71,8 @@ async fn running_the_node_works_and_can_be_interrupted() {
#[tokio::test]
async fn running_two_nodes_with_the_same_ws_port_should_work() {
common::run_with_timeout(Duration::from_secs(60 * 10), async move {
fn start_node() -> Child {
Command::new(cargo_bin("substrate"))
.stdout(process::Stdio::piped())
.stderr(process::Stdio::piped())
.args(&["--dev", "--tmp", "--ws-port=45789", "--no-hardware-benchmarks"])
.spawn()
.unwrap()
}

let mut first_node = common::KillChildOnDrop(start_node());
let mut second_node = common::KillChildOnDrop(start_node());
let mut first_node = common::KillChildOnDrop(common::start_node());
let mut second_node = common::KillChildOnDrop(common::start_node());

let stderr = first_node.stderr.take().unwrap();
let ws_url = common::extract_info_from_output(stderr).0.ws_url;
Expand Down
2 changes: 1 addition & 1 deletion bin/node/cli/tests/telemetry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use std::{process, time::Duration};

use crate::common::KillChildOnDrop;

pub mod common;
use substrate_cli_test_utils as common;
pub mod websocket_server;

#[tokio::test]
Expand Down
2 changes: 1 addition & 1 deletion bin/node/cli/tests/temp_base_path_works.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use std::{
time::Duration,
};

pub mod common;
use substrate_cli_test_utils as common;

#[allow(dead_code)]
// Apparently `#[ignore]` doesn't actually work to disable this one.
Expand Down
6 changes: 2 additions & 4 deletions frame/support/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -371,16 +371,14 @@ macro_rules! parameter_types {

/// Set the value of this parameter type in the storage.
///
/// This needs to be executed in an externalities provided
/// environment.
/// This needs to be executed in an externalities provided environment.
pub fn set(value: &$type) {
$crate::storage::unhashed::put(&Self::key(), value);
}

/// Returns the value of this parameter type.
///
/// This needs to be executed in an externalities provided
/// environment.
/// This needs to be executed in an externalities provided environment.
#[allow(unused)]
pub fn get() -> $type {
$crate::storage::unhashed::get(&Self::key()).unwrap_or_else(|| $value)
Expand Down
58 changes: 56 additions & 2 deletions frame/support/src/traits/hooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,10 +197,10 @@ impl OnRuntimeUpgrade for Tuple {
weight
}

#[cfg(feature = "try-runtime")]
/// We are executing pre- and post-checks sequentially in order to be able to test several
/// consecutive migrations for the same pallet without errors. Therefore pre and post upgrade
/// hooks for tuples are a noop.
#[cfg(feature = "try-runtime")]
fn try_on_runtime_upgrade(checks: bool) -> Result<Weight, &'static str> {
let mut weight = Weight::zero();
for_tuples!( #( weight = weight.saturating_add(Tuple::try_on_runtime_upgrade(checks)?); )* );
Expand Down Expand Up @@ -359,10 +359,64 @@ pub trait OnTimestampSet<Moment> {
#[cfg(test)]
mod tests {
use super::*;
use sp_io::TestExternalities;

#[cfg(feature = "try-runtime")]
#[test]
fn on_runtime_upgrade_pre_post_executed_tuple() {
crate::parameter_types! {
pub static Pre: Vec<&'static str> = Default::default();
pub static Post: Vec<&'static str> = Default::default();
}

macro_rules! impl_test_type {
($name:ident) => {
struct $name;
impl OnRuntimeUpgrade for $name {
fn on_runtime_upgrade() -> Weight {
Default::default()
}

#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
Pre::mutate(|s| s.push(stringify!($name)));
Ok(Vec::new())
}

#[cfg(feature = "try-runtime")]
fn post_upgrade(_: Vec<u8>) -> Result<(), &'static str> {
Post::mutate(|s| s.push(stringify!($name)));
Ok(())
}
}
};
}

impl_test_type!(Foo);
impl_test_type!(Bar);
impl_test_type!(Baz);

TestExternalities::default().execute_with(|| {
Foo::try_on_runtime_upgrade(true).unwrap();
assert_eq!(Pre::take(), vec!["Foo"]);
assert_eq!(Post::take(), vec!["Foo"]);

<(Foo, Bar, Baz)>::try_on_runtime_upgrade(true).unwrap();
assert_eq!(Pre::take(), vec!["Foo", "Bar", "Baz"]);
assert_eq!(Post::take(), vec!["Foo", "Bar", "Baz"]);

<((Foo, Bar), Baz)>::try_on_runtime_upgrade(true).unwrap();
assert_eq!(Pre::take(), vec!["Foo", "Bar", "Baz"]);
assert_eq!(Post::take(), vec!["Foo", "Bar", "Baz"]);

<(Foo, (Bar, Baz))>::try_on_runtime_upgrade(true).unwrap();
assert_eq!(Pre::take(), vec!["Foo", "Bar", "Baz"]);
assert_eq!(Post::take(), vec!["Foo", "Bar", "Baz"]);
});
}

#[test]
fn on_initialize_and_on_runtime_upgrade_weight_merge_works() {
use sp_io::TestExternalities;
struct Test;

impl OnInitialize<u8> for Test {
Expand Down
23 changes: 23 additions & 0 deletions test-utils/cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[package]
name = "substrate-cli-test-utils"
description = "CLI testing utilities"
version = "0.1.0"
authors = ["Parity Technologies <[email protected]>"]
edition = "2021"
license = "Apache-2.0"
homepage = "https://substrate.io"
repository = "https:/paritytech/substrate/"
publish = false

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
substrate-rpc-client = { path = "../../utils/frame/rpc/client" }
assert_cmd = "2.0.10"
nix = "0.26.2"
regex = "1.7.3"
tempfile = "3.5.0"
tokio = { version = "1.22.0", features = ["full"] }
node-primitives = { path = "../../bin/node/primitives" }
futures = "0.3.28"
134 changes: 134 additions & 0 deletions bin/node/cli/tests/common.rs → test-utils/cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,146 @@ use nix::{
use node_primitives::{Hash, Header};
use regex::Regex;
use std::{
env,
io::{BufRead, BufReader, Read},
ops::{Deref, DerefMut},
path::{Path, PathBuf},
process::{self, Child, Command},
time::Duration,
};
use tokio::io::{AsyncBufReadExt, AsyncRead};

/// Starts a new Substrate node in development mode with a temporary chain.
///
/// This function creates a new Substrate node using the `substrate` binary.
/// It configures the node to run in development mode (`--dev`) with a temporary chain (`--tmp`),
/// sets the WebSocket port to 45789 (`--ws-port=45789`).
///
/// # Returns
///
/// A [`Child`] process representing the spawned Substrate node.
///
/// # Panics
///
/// This function will panic if the `substrate` binary is not found or if the node fails to start.
///
/// # Examples
///
/// ```ignore
/// use my_crate::start_node;
///
/// let child = start_node();
/// // Interact with the Substrate node using the WebSocket port 45789.
/// // When done, the node will be killed when the `child` is dropped.
/// ```
///
/// [`Child`]: std::process::Child
pub fn start_node() -> Child {
Command::new(cargo_bin("substrate"))
.stdout(process::Stdio::piped())
.stderr(process::Stdio::piped())
.args(&["--dev", "--tmp", "--ws-port=45789", "--no-hardware-benchmarks"])
.spawn()
.unwrap()
}

/// Builds the Substrate project using the provided arguments.
///
/// This function reads the CARGO_MANIFEST_DIR environment variable to find the root workspace
/// directory. It then runs the `cargo b` command in the root directory with the specified
/// arguments.
///
/// This can be useful for building the Substrate binary with a desired set of features prior
/// to using the binary in a CLI test.
///
/// # Arguments
///
/// * `args: &[&str]` - A slice of string references representing the arguments to pass to the
/// `cargo b` command.
///
/// # Panics
///
/// This function will panic if:
///
/// * The CARGO_MANIFEST_DIR environment variable is not set.
/// * The root workspace directory cannot be determined.
/// * The 'cargo b' command fails to execute.
/// * The 'cargo b' command returns a non-successful status.
///
/// # Examples
///
/// ```ignore
/// build_substrate(&["--features=try-runtime"]);
/// ```
pub fn build_substrate(args: &[&str]) {
// Get the root workspace directory from the CARGO_MANIFEST_DIR environment variable
let manifest_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
let root_dir = std::path::Path::new(&manifest_dir)
.parent()
.expect("Failed to find root workspace directory");
let output = Command::new("cargo")
.arg("b")
liamaharon marked this conversation as resolved.
Show resolved Hide resolved
.args(args)
.current_dir(root_dir)
.output()
.expect(format!("Failed to execute 'cargo b' with args {:?}'", args).as_str());

if !output.status.success() {
panic!(
"Failed to execute 'cargo b' with args {:?}': \n{}",
args,
String::from_utf8_lossy(&output.stderr)
);
}
}

/// Takes a readable tokio stream (e.g. from a child process `ChildStderr` or `ChildStdout`) and
/// a `Regex` pattern, and checks each line against the given pattern as it is produced.
/// The function returns OK(()) as soon as a line matching the pattern is found, or an Err if
/// the stream ends without any lines matching the pattern.
///
/// # Arguments
///
/// * `child_stream` - An async tokio stream, e.g. from a child process `ChildStderr` or
/// `ChildStdout`.
/// * `re` - A `Regex` pattern to search for in the stream.
///
/// # Returns
///
/// * `Ok(())` if a line matching the pattern is found.
/// * `Err(String)` if the stream ends without any lines matching the pattern.
///
/// # Examples
///
/// ```ignore
/// use regex::Regex;
/// use tokio::process::Command;
/// use tokio::io::AsyncRead;
///
/// # async fn run() {
/// let child = Command::new("some-command").stderr(std::process::Stdio::piped()).spawn().unwrap();
/// let stderr = child.stderr.unwrap();
/// let re = Regex::new("error:").unwrap();
///
/// match wait_for_pattern_match_in_stream(stderr, re).await {
/// Ok(()) => println!("Error found in stderr"),
/// Err(e) => println!("Error: {}", e),
/// }
/// # }
/// ```
pub async fn wait_for_stream_pattern_match<R>(stream: R, re: Regex) -> Result<(), String>
where
R: AsyncRead + Unpin,
{
let mut stdio_reader = tokio::io::BufReader::new(stream).lines();
while let Ok(Some(line)) = stdio_reader.next_line().await {
match re.find(line.as_str()) {
Some(_) => return Ok(()),
None => (),
}
}
Err(String::from("Stream closed without any lines matching the regex."))
}

/// Run the given `future` and panic if the `timeout` is hit.
pub async fn run_with_timeout(timeout: Duration, future: impl futures::Future<Output = ()>) {
Expand Down
Loading