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

try-runtime-cli: execute-block & create-snapshot tests #14343

Merged
merged 24 commits into from
Jun 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
4bb74f2
execute-block test
Szegoo Jun 11, 2023
cb9720c
test create-snapshot
Szegoo Jun 12, 2023
2644c25
oops
Szegoo Jun 12, 2023
64ed955
Update utils/frame/try-runtime/cli/tests/create_snapshot.rs
Szegoo Jun 15, 2023
aa7e6a7
Update utils/frame/try-runtime/cli/tests/create_snapshot.rs
Szegoo Jun 15, 2023
2989dfc
Update utils/frame/try-runtime/cli/tests/create_snapshot.rs
Szegoo Jun 15, 2023
af1cfde
remove snapshot
Szegoo Jun 15, 2023
c1d5b80
execute block: new log
Szegoo Jun 15, 2023
c3a964d
use prefix & make tempfile a dev dependencie
Szegoo Jun 15, 2023
e7a54ab
Update utils/frame/try-runtime/cli/tests/execute_block.rs
Szegoo Jun 16, 2023
d3a9ca9
Update utils/frame/try-runtime/cli/tests/create_snapshot.rs
Szegoo Jun 16, 2023
6ce396e
".git/.scripts/commands/fmt/fmt.sh"
Jun 16, 2023
7d274e6
Merge remote-tracking branch 'origin/master' into try-runtime-tests
Jun 17, 2023
f439f28
--at option in execute-block test
Szegoo Jun 17, 2023
84a27de
fixes & use --at option in create-snapshot test
Szegoo Jun 17, 2023
7581859
hmm
Szegoo Jun 17, 2023
8fc182a
fmt
Szegoo Jun 17, 2023
b7c157b
remove nonsense
Szegoo Jun 18, 2023
f1c77b4
Update utils/frame/try-runtime/cli/tests/create_snapshot.rs
Szegoo Jun 21, 2023
08b881c
Update utils/frame/try-runtime/cli/tests/execute_block.rs
Szegoo Jun 21, 2023
e78e7e4
remove unnecessary test modules
Szegoo Jun 21, 2023
4e3e29b
try to load snapshot file
Szegoo Jun 21, 2023
2c689d5
Merge branch 'paritytech:master' into try-runtime-tests
Szegoo Jun 21, 2023
daab1cc
fix
Szegoo Jun 21, 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
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions frame/executive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,12 @@ where
);
}

frame_support::log::info!(
target: LOG_TARGET,
"try-runtime: Block #{:?} successfully executed",
Copy link
Member

@ggwpez ggwpez Jun 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some ideas, we could do stuff here like:

  • State trace (output of all modified storage keys)
  • Print all executed calls + Events
  • Consumed weight
  • Block size etc

Probably most of it in JSON, so we can render it eventually (like chopsticks already does for state changes).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be done in this PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. Just some ideas for the future 😄

header.number(),
);

Ok(frame_system::Pallet::<System>::block_weight().total())
}

Expand Down
1 change: 1 addition & 0 deletions test-utils/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
substrate-rpc-client = { path = "../../utils/frame/rpc/client" }
sp-rpc = { version = "6.0.0", path = "../../primitives/rpc" }
assert_cmd = "2.0.10"
nix = "0.26.2"
regex = "1.7.3"
Expand Down
23 changes: 22 additions & 1 deletion test-utils/cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use nix::{
};
use node_primitives::{Hash, Header};
use regex::Regex;
use sp_rpc::{list::ListOrValue, number::NumberOrHex};
use std::{
env,
io::{BufRead, BufReader, Read},
Expand Down Expand Up @@ -177,7 +178,8 @@ pub async fn wait_n_finalized_blocks(n: usize, url: &str) {
use substrate_rpc_client::{ws_client, ChainApi};

let mut built_blocks = std::collections::HashSet::new();
let mut interval = tokio::time::interval(Duration::from_secs(2));
let block_duration = Duration::from_secs(2);
let mut interval = tokio::time::interval(block_duration);
let rpc = ws_client(url).await.unwrap();

loop {
Expand Down Expand Up @@ -220,6 +222,25 @@ pub async fn run_node_for_a_while(base_path: &Path, args: &[&str]) {
.await
}

pub async fn block_hash(block_number: u64, url: &str) -> Result<Hash, String> {
use substrate_rpc_client::{ws_client, ChainApi};

let rpc = ws_client(url).await.unwrap();

let result = ChainApi::<(), Hash, Header, ()>::block_hash(
&rpc,
Some(ListOrValue::Value(NumberOrHex::Number(block_number))),
)
.await
.map_err(|_| "Couldn't get block hash".to_string())?;

match result {
ListOrValue::Value(maybe_block_hash) if maybe_block_hash.is_some() =>
Ok(maybe_block_hash.unwrap()),
_ => Err("Couldn't get block hash".to_string()),
}
}

pub struct KillChildOnDrop(pub Child);

impl KillChildOnDrop {
Expand Down
2 changes: 2 additions & 0 deletions utils/frame/try-runtime/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ zstd = { version = "0.12.3", default-features = false }

[dev-dependencies]
assert_cmd = "2.0.10"
node-primitives = { path = "../../../../bin/node/primitives" }
regex = "1.7.3"
substrate-cli-test-utils = { path = "../../../../test-utils/cli" }
tempfile = "3.1.0"
tokio = "1.27.0"

[features]
Expand Down
95 changes: 95 additions & 0 deletions utils/frame/try-runtime/cli/tests/create_snapshot.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// This file is part of Substrate.

// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

#![cfg(unix)]
#![cfg(feature = "try-runtime")]

use assert_cmd::cargo::cargo_bin;
use node_primitives::Hash;
use regex::Regex;
use remote_externalities::{Builder, Mode, OfflineConfig, SnapshotConfig};
use sp_runtime::testing::{Block as RawBlock, ExtrinsicWrapper};
use std::{
path::{Path, PathBuf},
process,
time::Duration,
};
use substrate_cli_test_utils as common;
use tokio::process::{Child, Command};

type Block = RawBlock<ExtrinsicWrapper<Hash>>;

#[tokio::test]
async fn create_snapshot_works() {
// Build substrate so binaries used in the test use the latest code.
common::build_substrate(&["--features=try-runtime"]);

let temp_dir = tempfile::Builder::new()
.prefix("try-runtime-cli-test-dir")
.tempdir()
.expect("Failed to create a tempdir");
let snap_file_path = temp_dir.path().join("snapshot.snap");

common::run_with_timeout(Duration::from_secs(60), async move {
fn create_snapshot(ws_url: &str, snap_file: &PathBuf, at: Hash) -> Child {
Command::new(cargo_bin("substrate"))
.stdout(process::Stdio::piped())
.stderr(process::Stdio::piped())
.args(&["try-runtime", "--runtime=existing"])
.args(&["create-snapshot", format!("--uri={}", ws_url).as_str()])
.arg(snap_file)
.args(&["--at", format!("{:?}", at).as_str()])
.kill_on_drop(true)
.spawn()
.unwrap()
}

// Start a node and wait for it to begin finalizing blocks
let mut node = common::KillChildOnDrop(common::start_node());
let ws_url = common::extract_info_from_output(node.stderr.take().unwrap()).0.ws_url;
common::wait_n_finalized_blocks(3, &ws_url).await;

let block_number = 2;
let block_hash = common::block_hash(block_number, &ws_url).await.unwrap();

// Try to create a snapshot.
let mut snapshot_creation = create_snapshot(&ws_url, &snap_file_path, block_hash);

let re = Regex::new(r#".*writing snapshot of (\d+) bytes to .*"#).unwrap();
let matched =
common::wait_for_stream_pattern_match(snapshot_creation.stderr.take().unwrap(), re)
.await;

// Assert that the snapshot creation succeded.
assert!(matched.is_ok(), "Failed to create snapshot");

let snapshot_is_on_disk = Path::new(&snap_file_path).exists();
assert!(snapshot_is_on_disk, "Snapshot was not written to disk");

// Try and load the snapshot we have created by running `create-snapshot`.
let snapshot_loading_result = Builder::<Block>::new()
.mode(Mode::Offline(OfflineConfig {
state_snapshot: SnapshotConfig { path: snap_file_path },
}))
.build()
.await;

assert!(snapshot_loading_result.is_ok(), "Snapshot couldn't be loaded");
})
.await;
}
70 changes: 70 additions & 0 deletions utils/frame/try-runtime/cli/tests/execute_block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// This file is part of Substrate.

// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

#![cfg(unix)]
#![cfg(feature = "try-runtime")]

use assert_cmd::cargo::cargo_bin;
use node_primitives::Hash;
use regex::Regex;
use std::{process, time::Duration};
use substrate_cli_test_utils as common;
use tokio::process::{Child, Command};

#[tokio::test]
async fn block_execution_works() {
// Build substrate so binaries used in the test use the latest code.
common::build_substrate(&["--features=try-runtime"]);

common::run_with_timeout(Duration::from_secs(60), async move {
fn execute_block(ws_url: &str, at: Hash) -> Child {
Command::new(cargo_bin("substrate"))
.stdout(process::Stdio::piped())
.stderr(process::Stdio::piped())
.args(&["try-runtime", "--runtime=existing"])
.args(&["execute-block"])
.args(&["live", format!("--uri={}", ws_url).as_str()])
.args(&["--at", format!("{:?}", at).as_str()])
.kill_on_drop(true)
.spawn()
.unwrap()
}

// Start a node and wait for it to begin finalizing blocks
let mut node = common::KillChildOnDrop(common::start_node());
let ws_url = common::extract_info_from_output(node.stderr.take().unwrap()).0.ws_url;
common::wait_n_finalized_blocks(3, &ws_url).await;

let block_number = 1;
let block_hash = common::block_hash(block_number, &ws_url).await.unwrap();

// Try to execute the block.
let mut block_execution = execute_block(&ws_url, block_hash);

// The execute-block command is actually executing the next block.
let expected_output =
format!(r#".*Block #{} successfully executed"#, block_number.saturating_add(1));
let re = Regex::new(expected_output.as_str()).unwrap();
let matched =
common::wait_for_stream_pattern_match(block_execution.stderr.take().unwrap(), re).await;

// Assert that the block-execution process has executed a block.
assert!(matched.is_ok());
})
.await;
}
88 changes: 43 additions & 45 deletions utils/frame/try-runtime/cli/tests/follow_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,49 +17,47 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.

#![cfg(unix)]

#[cfg(feature = "try-runtime")]
mod tests {
use assert_cmd::cargo::cargo_bin;
use regex::Regex;
use std::{
process::{self},
time::Duration,
};
use substrate_cli_test_utils as common;
use tokio::process::{Child, Command};

#[tokio::test]
async fn follow_chain_works() {
// Build substrate so binaries used in the test use the latest code.
common::build_substrate(&["--features=try-runtime"]);

common::run_with_timeout(Duration::from_secs(60), async move {
fn start_follow(ws_url: &str) -> Child {
Command::new(cargo_bin("substrate"))
.stdout(process::Stdio::piped())
.stderr(process::Stdio::piped())
.args(&["try-runtime", "--runtime=existing"])
.args(&["follow-chain", format!("--uri={}", ws_url).as_str()])
.kill_on_drop(true)
.spawn()
.unwrap()
}

// Start a node and wait for it to begin finalizing blocks
let mut node = common::KillChildOnDrop(common::start_node());
let ws_url = common::extract_info_from_output(node.stderr.take().unwrap()).0.ws_url;
common::wait_n_finalized_blocks(1, &ws_url).await;

// Kick off the follow-chain process and wait for it to process at least 3 blocks.
let mut follow = start_follow(&ws_url);
let re = Regex::new(r#".*executed block ([3-9]|[1-9]\d+).*"#).unwrap();
let matched =
common::wait_for_stream_pattern_match(follow.stderr.take().unwrap(), re).await;

// Assert that the follow-chain process has followed at least 3 blocks.
assert!(matches!(matched, Ok(_)));
})
.await;
}
#![cfg(feature = "try-runtime")]

use assert_cmd::cargo::cargo_bin;
use regex::Regex;
use std::{
process::{self},
time::Duration,
};
use substrate_cli_test_utils as common;
use tokio::process::{Child, Command};

#[tokio::test]
async fn follow_chain_works() {
// Build substrate so binaries used in the test use the latest code.
common::build_substrate(&["--features=try-runtime"]);

common::run_with_timeout(Duration::from_secs(60), async move {
fn start_follow(ws_url: &str) -> Child {
Command::new(cargo_bin("substrate"))
.stdout(process::Stdio::piped())
.stderr(process::Stdio::piped())
.args(&["try-runtime", "--runtime=existing"])
.args(&["follow-chain", format!("--uri={}", ws_url).as_str()])
.kill_on_drop(true)
.spawn()
.unwrap()
}

// Start a node and wait for it to begin finalizing blocks
let mut node = common::KillChildOnDrop(common::start_node());
let ws_url = common::extract_info_from_output(node.stderr.take().unwrap()).0.ws_url;
common::wait_n_finalized_blocks(1, &ws_url).await;

// Kick off the follow-chain process and wait for it to process at least 3 blocks.
let mut follow = start_follow(&ws_url);
let re = Regex::new(r#".*executed block ([3-9]|[1-9]\d+).*"#).unwrap();
let matched =
common::wait_for_stream_pattern_match(follow.stderr.take().unwrap(), re).await;

// Assert that the follow-chain process has followed at least 3 blocks.
assert!(matched.is_ok());
})
.await;
}